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 相关文章推荐
jquery统计复选框选中示例
Nov 05 Javascript
jquery实现的图片点击滚动效果
Apr 29 Javascript
jQuery处理json数据返回数组和输出的方法
Mar 11 Javascript
javascript超过容器后显示省略号效果的方法(兼容一行或者多行)
Jul 14 Javascript
每个程序员都需要学习 JavaScript 的7个理由小结
Sep 03 Javascript
AngularJS Phonecat实例讲解
Nov 21 Javascript
微信小程序 在线支付功能的实现
Mar 14 Javascript
基于vue实现网站前台的权限管理(前后端分离实践)
Jan 13 Javascript
有关vue 开发钉钉 H5 微应用 dd.ready() 不执行问题及快速解决方案
May 09 Javascript
原生JavaScript写出Tabs标签页的实例代码
Jul 20 Javascript
ant-design-vue中的select选择器,对输入值的进行筛选操作
Oct 24 Javascript
JavaScript实现复选框全选功能
Apr 11 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
PHP-MySQL教程归纳总结
2008/06/07 PHP
用PHP获取Google AJAX Search API 数据的代码
2010/03/12 PHP
PHP实现原比例生成缩略图的方法
2016/02/03 PHP
jquery中dom操作和事件的实例学习 仿yahoo邮箱登录框的提示效果
2011/11/30 Javascript
js时间戳格式化成日期格式的多种方法
2013/11/11 Javascript
Javascript基础教程之数组 array
2015/01/18 Javascript
JQuery radio(单选按钮)操作方法汇总
2015/04/15 Javascript
js实现的简单radio背景颜色选择器代码
2015/08/18 Javascript
jquery实现的伪分页效果代码
2015/10/29 Javascript
解决WordPress使用CDN后博文无法评论的错误
2015/12/15 Javascript
给angular加上动画效遇到的问题总结
2016/02/17 Javascript
Summernote实现图片上传功能的简单方法
2016/07/11 Javascript
jquery之别踩白块游戏的简单实现
2016/07/25 Javascript
jQuery实现html双向绑定功能示例
2017/10/09 jQuery
详解Ant Design of React的安装和使用方法
2018/12/27 Javascript
浅谈一个webpack构建速度优化误区
2019/06/24 Javascript
js图数据结构处理 迪杰斯特拉算法代码实例
2019/09/11 Javascript
Vue修改项目启动端口号方法
2019/11/07 Javascript
JS实现横向轮播图(初级版)
2020/06/24 Javascript
Python原始字符串(raw strings)用法实例
2014/10/13 Python
简化Python的Django框架代码的一些示例
2015/04/20 Python
Ubuntu16.04/树莓派Python3+opencv配置教程(分享)
2018/04/02 Python
Python如何获取文件路径/目录
2020/09/22 Python
详解向scrapy中的spider传递参数的几种方法(2种)
2020/09/28 Python
Python爬取微信小程序Charles实现过程图解
2020/09/29 Python
HTML5 Canvas图像模糊完美解决办法
2018/02/06 HTML / CSS
英国最大的奢侈珠宝和手表网站:C W Sellors
2017/02/10 全球购物
美国家居装饰和豪华家具购物网站:One Kings Lane
2018/12/24 全球购物
2014年教师节国旗下讲话稿
2014/09/10 职场文书
个人年终总结开头
2015/03/06 职场文书
论文致谢词范文
2015/05/14 职场文书
中学教师教学工作总结
2015/08/13 职场文书
优秀范文:《但愿人长久》教学反思3篇
2019/10/24 职场文书
PhpSpreadsheet中文文档 | Spreadsheet操作教程实例
2021/04/01 PHP
用Python简陋模拟n阶魔方
2021/04/17 Python
据Python爬虫不靠谱预测可知今年双十一销售额将超过6000亿元
2021/11/11 Python