一.什么是Promise?
ES6 异步编程的一种解决方案,比传统的方案(回调函数和事件)更加的合理和强大。大家都知道传统解决异步编程用的是回调函数套回调函数,简称回调地域。以前用JQuery的朋友应该是相当熟悉了。维护起来很难搞。
回调地域
var say = function (name, callback) { setTimeout(function () { console.log(name); callback(); }, 1000); } // 回调地域 say("张三", function () { say("李四", function () { say("王麻子", function () { console.log("班长"); }); }); });
Promise
var say = function (order) { return new Promise(function (resolve, reject) { setTimeout(function () { console.log(name); //在异步操作执行完后执行 resolve() 函数 resolve(); }, 1000); }); } say("张三").then(function () { //仍然返回一个 Promise 对象 return say("李四"); }).then(function () { return say("王麻子"); }).then(function () { console.log('班长'); }).catch(function (err) { // 捕获异常 console.log(err); })
二.Promise的优点
- 异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
- 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、resolved(已成功)和rejected(已失败)。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为resolved和从pending变为rejected。
- promise内部发生错误,不会影响到外部程序的执行。
- 无法取消Promise。一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
三.用法
创建promise实例
const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
Promise.all 方法: (promises) => {}
function PromiseAll(promises){ return new Promise((resolve, reject)=>{ if(!Array.isArray(promises)){ throw new TypeError("promises must be an array") } let result = [] let count = 0 promises.forEach((promise, index) => { promise.then((res)=>{ result[index] = res count++ count === promises.length && resolve(result) }, (err)=>{ reject(err) }) }) }) }
Promise.race 方法: (promises) => {}
promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态。Promise.race = function(promiseArr) { return new Promise((resolve, reject) => { promiseArr.forEach(p => { Promise.resolve(p).then(val => { resolve(val) }, err => { rejecte(err) }) }) }) }
Promise.finally():
finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
Promise.finally()方法的使用场景:强制关闭弹框(个人理解),就是无论你成功还是失败总得做某件事的时候Promise.prototype.finally = function (cb) { return this.then(function (value) { return Promise.resolve(cb()).then(function () { return value }) }, function (err) { return Promise.resolve(cb()).then(function () { throw err }) }) }
Promise.any():
可用于以并行和竞争方式执行独立的异步操作,以获取任何第一个完成的 promise 的值。
应用场景:1.在页面中,我们可能需要同时请求多个接口,并且只要其中任意一个接口请求成功即可展示数据。
2.在某些情况下,我们需要在一定时间内获取某些数据或执行一系列操作,如果超过了指定时间还没完成,就需要执行后续处理。这时候,我们可以使用 Promise.race 来设置超时时间,但是这样只能处理一个任务,在需要处理多个任务的情况下,我们可以使用 Promise.any 来实现
Promise.any = function(promiseArr) {
let index = 0
return new Promise((resolve, reject) => {
if (promiseArr.length === 0) return
promiseArr.forEach((p, i) => {
Promise.resolve(p).then(val => {
resolve(val)
}, err => {
index++
if (index === promiseArr.length) {
reject(new AggregateError('All promises were rejected'))
}
})
})
})
}