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 相关文章推荐
js实现的真正的iframe高度自适应(兼容IE,FF,Opera)
Mar 07 Javascript
禁止IE用右键的JS代码
Dec 30 Javascript
IE6下拉框图层问题探讨及解决
Jan 03 Javascript
Jquery响应回车键直接提交表单操作代码
Jul 25 Javascript
js检查是否关闭浏览器的方法
Aug 02 Javascript
详解打造 Vue.js 可复用组件
Mar 24 Javascript
浅谈vue路径优化之resolve
Oct 13 Javascript
Vue 项目中遇到的跨域问题及解决方法(后台php)
Mar 28 Javascript
React组件重构之嵌套+继承及高阶组件详解
Jul 19 Javascript
django使用channels2.x实现实时通讯
Nov 28 Javascript
Nuxt.js开启SSR渲染的教程详解
Nov 30 Javascript
vue实现同时设置多个倒计时
May 20 Vue.js
详解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
PHP 显示客户端IP与服务器IP的代码
2010/10/12 PHP
php curl获取网页内容(IPV6下超时)的解决办法
2013/07/16 PHP
SAE实时日志接口SDK用法示例
2016/10/09 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
关于js获取radio和select的属性并控制的代码
2011/05/12 Javascript
namespace.js Javascript的命名空间库
2011/10/11 Javascript
javascript数组去重3种方法的性能测试与比较
2013/03/26 Javascript
jquery网页元素拖拽插件效果及实现
2013/08/05 Javascript
基于jquery实现一张图片点击鼠标放大再点缩小
2013/09/29 Javascript
使用js如何实现全选与全不选
2013/12/30 Javascript
一个html5播放视频的video控件只支持android的默认格式mp4和3gp
2014/05/08 Javascript
JavaScript删除指定子元素代码实例
2015/01/13 Javascript
jQuery实现下拉框功能实例代码
2016/05/06 Javascript
json实现添加、遍历与删除属性的方法
2016/06/17 Javascript
js智能获取浏览器版本UA信息的方法
2016/08/08 Javascript
JS动态的把左边列表添加到右边的实现代码(可上下移动)
2016/11/17 Javascript
详解NODEJS基于FFMPEG视频推流测试
2017/11/17 NodeJs
Angular6 写一个简单的Select组件示例
2018/08/20 Javascript
如何换个角度使用VUE过滤器详解
2019/09/11 Javascript
layui点击左侧导航栏,实现不刷新整个页面,只刷新局部的方法
2019/09/25 Javascript
Python os模块中的isfile()和isdir()函数均返回false问题解决方法
2015/02/04 Python
Django的HttpRequest和HttpResponse对象详解
2018/01/26 Python
Python socket实现的简单通信功能示例
2018/08/21 Python
使用python进行广告点击率的预测的实现
2019/07/04 Python
对python3中的RE(正则表达式)-详细总结
2019/07/23 Python
pytorch打印网络结构的实例
2019/08/19 Python
Python中的sys.stdout.write实现打印刷新功能
2020/02/21 Python
5行Python代码实现图像分割的步骤详解
2020/05/25 Python
毕业生大学生活自我总结
2014/01/31 职场文书
社区敬老月活动实施方案
2014/02/17 职场文书
公司办公室岗位职责
2014/03/19 职场文书
地球一小时倡议书
2014/04/15 职场文书
班组拓展活动方案
2014/08/14 职场文书
国际贸易实务实训报告
2014/11/05 职场文书
党员发展大会主持词
2015/07/03 职场文书
动画《新网球王子 U-17 WORLD CUP》希腊队PV公开
2022/04/02 日漫