ES6 Promise对象概念及用法实例详解


Posted in Javascript onOctober 15, 2019

本文实例讲述了ES6 Promise对象概念及用法。分享给大家供大家参考,具体如下:

参考文章:ECMAScript 6 入门

一、 Promise是什么

Promise是异步编程的一种解决方案,它是一个容器,里面保存着某个未来才会结束的事件的结果。它有三种状态,只有异步操作的结果才能决定当前的状态,不受外界因素的影响。而一旦状态改变,就不会再变,也就是状态凝固了(resolved),任何时候都可以得到这个结果。

ES6 Promise对象概念及用法实例详解

Promise的缺点:
1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
3. 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

二、Promise的用法

/**
 * 创建Promise实例
 * @type {Promise}
 * @param resolve 在异步操作成功时调用
 * @param reject 在异步操作失败时调用
 */
const promise = new Promise(function(resolve, reject) {
  // ... some code
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
//调用Promise
promise.then(function(value) {
 // success
}, function(error) {
 // failure
});

Promise 新建后就会立即执行。

let promise = new Promise(function(resolve, reject) {
 console.log('Promise');
 resolve();
});
promise.then(function() {
 console.log('resolved.');
});
console.log('Hi!');
// Promise (Promise 新建后立即执行,所以首先输出的是Promise)
// Hi!
// resolved (then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出)

如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例。

const p1 = new Promise(function (resolve, reject) {
 setTimeout(() => reject(new Error('fail')), 3000)
})
const p2 = new Promise(function (resolve, reject) {
 setTimeout(() => resolve(p1), 1000)
})
p2
 .then(result => console.log(result))
 .catch(error => console.log(error))
// Error: fail

上面代码中,p1是一个 Promise,3 秒之后变为rejected。p2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数。

三、Promise原型上的方法

Promise.prototype.then()

  1. then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
  2. then方法返回的是一个新的Promise实例,但不是原来那个Promise实例。因此可以采用链式写法,即then方法后面再调用另一个then方法。
getJSON("/post/1.json").then(
 post => getJSON(post.commentURL)
).then(
 comments => console.log("resolved: ", comments),
 err => console.log("rejected: ", err)
);

Promise.prototype.catch()

  1. Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
  2. Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。
getJSON('/post/1.json').then(function(post) {
 return getJSON(post.commentURL);
}).then(function(comments) {
 // some code
}).catch(function(error) {
 // 处理前面三个Promise产生的错误
});
//上面代码中,一共有三个 Promise 对象:一个由getJSON产生,两个由then产生。它们之中任何一个抛出的错误,都会被最后一个catch捕获。

Promise.prototype.finally()

  • finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
  • finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。

四、Promise的方法

Promise.all()

  1. Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
  2. const p = Promise.all([p1, p2, p3]);
    1. 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
    2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
  3. 如果p1、p2、p3有自己的catch方法,则不会触发p的catch方法,如果没有,才会调用Promise.all()的catch方法。
const p1 = new Promise((resolve, reject) => {
 resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
 throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
-------------------------------------------------------------------
const p1 = new Promise((resolve, reject) => {
 resolve('hello');
})
.then(result => result);
const p2 = new Promise((resolve, reject) => {
 throw new Error('报错了');
})
.then(result => result);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// Error: 报错了

Promise.race()

  1. Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
  2. race内部的一个实例率先改变状态,Promise.race()的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给Promise.race()的回调函数。

Promise.resolve()

  1. 有时需要将现有对象转为 Promise 对象,Promise.resolve方法就起到这个作用。
  2. Promise.resolve方法的参数分成四种情况。
    1. 参数是一个 Promise 实例:如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
    2. 参数是一个thenable对象:thenable对象指的是具有then方法的对象,Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
    3. 参数不是具有then方法的对象,或根本就不是对象:如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。
    4. 不带有任何参数:Promise.resolve方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。

需要注意的是,立即resolve的 Promise 对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时。

setTimeout(function () {
 console.log('three');
}, 0);
Promise.resolve().then(function () {
 console.log('two');
});
console.log('one');
// one
// two
// three

Promise.reject()

  1. Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。
  2. 注意,Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。
const thenable = {
 then(resolve, reject) {
  reject('出错了');
 }
};
Promise.reject(thenable)
.catch(e => {
 console.log(e === thenable)
})
// true

五、Promise的应用

包装http请求

在使用vue的过程中,我们用Promise对Axios进行了包装。

newAxios.post = function (url, params) {
 params = qs.stringify(params);
 return new Promise((resolve, reject) => {
  Axios.post(url, params)
   .then(res => {
    if (res.headers.warning === "redirect") {
     window.location.href = "/"
    } else {
     resolve(res);
    }
   })
   .catch(err => {
    reject(err);
   })
 })
};

处理异步请求

使用Promise.all()方法可以处理异步请求,比如某些请求需要在前面几个请求完成之后才触发。

后续待补充。

附:ECMAScript 6 入门本站下载地址:https://3water.com/books/551561.html

更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
javascript之ESC(第二类混淆)
May 06 Javascript
JavaScript内核之基本概念
Oct 21 Javascript
javascript实现tabs选项卡切换效果(扩展版)
Mar 19 Javascript
javascript预加载图片、css、js的方法示例介绍
Oct 14 Javascript
Jquery性能优化详解
May 15 Javascript
node.js入门教程
Jun 01 Javascript
JavaScript常用标签和方法总结
Sep 01 Javascript
javascript手风琴下拉菜单实现代码
Nov 12 Javascript
防止重复发送 Ajax 请求
Feb 15 Javascript
bootstrapTable+ajax加载数据 refresh更新数据
Aug 31 Javascript
一个手写的vue放大镜效果
Aug 09 Javascript
vue中keep-alive内置组件缓存的实例代码
Apr 16 Javascript
详解Vue.js 作用域、slot用法(单个slot、具名slot)
Oct 15 #Javascript
vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
Oct 15 #Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
Oct 15 #Javascript
vue使用@scroll监听滚动事件时,@scroll无效问题的解决方法详解
Oct 15 #Javascript
vue实现树形结构样式和功能的实例代码
Oct 15 #Javascript
谈谈IntersectionObserver懒加载的具体使用
Oct 15 #Javascript
js实现开关灯效果
Mar 30 #Javascript
You might like
深入了解 register_globals (附register_globals=off 网站打不开的解决方法)
2012/06/27 PHP
PHP批量查询WordPress留言者E-mail地址实现方法
2015/02/15 PHP
浅谈Coreseek、Sphinx-for-chinaese、Sphinx+Scws的区别
2016/12/15 PHP
javascript 流畅动画实现原理
2009/09/08 Javascript
为jQuery.Treeview添加右键菜单的实现代码
2010/10/22 Javascript
用jquery实现自定义风格的滑动条实现代码
2011/04/26 Javascript
js判断屏幕分辨率的代码
2013/07/16 Javascript
jquery更换文章内容与改变字体大小代码
2013/09/30 Javascript
jquery遍历之parent()和parents()的区别及parentsUntil()方法详解
2013/12/02 Javascript
jquery实现非叠加式的搜索框提示效果
2014/01/07 Javascript
angularjs 源码解析之injector
2016/08/22 Javascript
Web打印解决方案之证件套打的实现思路
2016/08/29 Javascript
jQuery获取select选中的option的value值实现方法
2016/08/29 Javascript
js实现碰撞检测特效代码分享
2016/10/16 Javascript
HTML5canvas 绘制一个圆环形的进度表示实例
2016/12/16 Javascript
解决JS外部文件中文注释出现乱码问题
2017/07/09 Javascript
JS简单实现滑动加载数据的方法示例
2017/10/18 Javascript
js+html实现点名系统功能
2019/11/05 Javascript
js实现全选和全不选功能
2020/07/28 Javascript
[03:59]第二届DOTA2亚洲邀请赛选手传记-VGJ.rOtk
2017/04/03 DOTA
python自动登录12306并自动点击验证码完成登录的实现源代码
2018/04/25 Python
python实战教程之自动扫雷
2018/07/13 Python
nohup后台启动Python脚本,log不刷新的解决方法
2019/01/14 Python
PyQT实现菜单中的复制,全选和清空的功能的方法
2019/06/17 Python
Python获取时间戳代码实例
2019/09/24 Python
ubuntu上安装python的实例方法
2019/09/30 Python
python打印n位数“水仙花数”(实例代码)
2019/12/25 Python
浅谈pytorch中的BN层的注意事项
2020/06/23 Python
英国标志性生活方式品牌:Skinnydip London
2019/12/15 全球购物
Auguste The Label官网:澳大利亚一家精品女装时尚品牌
2020/06/14 全球购物
Unix如何添加新的用户
2014/08/20 面试题
小区门卫值班制度
2014/01/24 职场文书
受伤赔偿协议书
2014/09/24 职场文书
2015年学生会工作总结范文
2015/03/31 职场文书
2019商业计划书格式、范文
2019/04/24 职场文书
CocosCreator如何实现划过的位置显示纹理
2021/04/14 Javascript