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 相关文章推荐
用Juery网页选项卡实现代码
Jun 13 Javascript
jquery实现动态改变div宽度和高度
May 08 Javascript
DEDECMS如何为文章添加HOT NEW标志图片
Aug 14 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
Sep 18 Javascript
JavaScript模版引擎的基本实现方法浅析
Feb 15 Javascript
jqGrid 学习笔记整理——进阶篇(一 )
Apr 17 Javascript
form+iframe解决跨域上传文件的方法
Nov 18 Javascript
使用Angular CLI快速创建Angular项目的一些基本概念和写法小结
Apr 22 Javascript
基于JavaScript实现瀑布流布局
Aug 15 Javascript
微信小程序扫描二维码获取信息实例详解
May 07 Javascript
微信小程序如何使用globalData的方法
Jun 06 Javascript
微信小程序实现动态列表项的顺序加载动画
Jul 25 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中处理模拟rewrite 效果
2006/12/09 PHP
Yii框架弹出窗口组件CJuiDialog用法分析
2017/01/07 PHP
PHP使用new StdClass()创建空对象的方法分析
2017/06/06 PHP
jQuery 获取对象 定位子对象
2010/05/31 Javascript
javascript动态加载实现方法一
2012/08/22 Javascript
Js日期选择自动填充到输入框(界面漂亮兼容火狐)
2013/08/02 Javascript
jquery事件与函数的使用介绍
2013/09/29 Javascript
jquery遍历数组与筛选数组的方法
2013/11/05 Javascript
JavaScript实现的日期控件具体代码
2013/11/18 Javascript
javascript页面动态显示时间变化示例代码
2013/12/18 Javascript
js购物车实现思路及代码(个人感觉不错)
2013/12/23 Javascript
JS替换文本域内的回车示例
2014/02/18 Javascript
jQuery实现自动调整字体大小的方法
2015/06/15 Javascript
jQuery Dialog对话框事件用法实例分析
2016/05/10 Javascript
Three.js学习之几何形状
2016/08/01 Javascript
详解Vue-cli中的静态资源管理(src/assets和static/的区别)
2018/06/19 Javascript
实例详解ztree在vue项目中使用并且带有搜索功能
2018/08/24 Javascript
JS函数进阶之继承用法实例分析
2020/01/15 Javascript
ES6学习教程之Promise用法详解
2020/11/22 Javascript
[00:32]2016完美“圣”典风云人物:Maybe宣传片
2016/12/05 DOTA
python创建线程示例
2014/05/06 Python
Python性能提升之延迟初始化
2016/12/04 Python
关于python中密码加盐的学习体会小结
2019/07/15 Python
用python wxpy管理微信公众号并利用微信获取自己的开源数据
2019/07/30 Python
python 队列基本定义与使用方法【初始化、赋值、判断等】
2019/10/24 Python
python将字符串转变成dict格式的实现
2019/11/18 Python
Python tornado上传文件的功能
2020/03/26 Python
python3的pip路径在哪
2020/06/23 Python
Python enumerate() 函数如何实现索引功能
2020/06/29 Python
Python使用tkinter实现小时钟效果
2021/02/22 Python
python 指定源路径来解决import问题的操作
2021/03/04 Python
静态成员和非静态成员的区别
2012/05/12 面试题
电大毕业个人生自我鉴定
2014/03/26 职场文书
企业优秀团员事迹材料
2014/08/20 职场文书
超市督导岗位职责
2015/04/10 职场文书
2015年电厂工作总结范文
2015/05/13 职场文书