共计 2485 个字符,预计需要花费 7 分钟才能阅读完成。
问题来了
Promise 有几种状态?
Promise 有什么优缺点?
Promise 构造函数是同步还是异步执行,then 呢?
Promise 和 setTimeout 的区别?
如何实现 Promise.all?
如何实现 Promise.finally?
Promise 知识点
1. Promise
1)定义
保存着某个未来才会结束的事件(异步操作)的容器
2)特点
(1)对象的状态不受外界影响。三个状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前状态。
(2)状态只能改变一次,任何时候都能得到该结果。两种状态改变的情况:pending->fulfilled、pending->rejected。状态一直保持,给 Promise 对象添加回调函数,能得到该结果。
3)优缺点
(1)可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数;Promise 对象提供统一的接口,是的控制异常操作更加容易。
(2)无法取消 Promise,一旦新建立即执行;若不设置回调函数,则 Promise 内部抛出的异常反应不到外部;pending 状态无法得知进展。
2. Promise.prototype.then()
1)定义
为 Promise 实例添加状态改变时的回调函数。.then(resolved 的回调函数,rejected 的回调函数[可选])
tips:
then 方法返回的是一个新的 Promise 实例(不是原来的那个 Promise 实例),因此可以链式,如:.then().then()。
采用链式的 then,可以指定一组按照次序执行的回调函数。
3. Promise.prototype.catch()
1)定义
then(null, rehection) 或.then(undefiend, rejection)的别名,用于指定发生错误时的回调函数。
tips:
promise 对象的错误具有“冒泡”性质,错误一直向后传递,直至被捕获。
promise 对象错误不会传递到外层代码,即不同于 try/catch,(报错后不会终止外层代码执行)。
4. Promise.prototype.finally()
1)定义
不论 Promise 对象最终状态如何,都会执行的操作(ES2018)。本质上是 then 方法的特例。
2)特点
不接受任何参数,不影响原 Promise 的状态。
3)实际应用
post 请求 loading,在请求结束后不论结果如何都关闭 loading
5. Promise.all()
作用:
将多个 Promise 实例,包装成一个 Promise 实例。
特点:
新 Promise 对象 (p) 的状态由 Promise 实例数组([p1, p2, p3])决定。
当 p1、p2、p3 状态都为 fulfilled,p 的状态为 fulfilled,p1、p2、p3 的返回值组成一个数组,传递给 p 的回调函数。
当 p1、p2、p3 中有一个状态为 rejected,p 的状态为 rejected,第一个被 reject 的实例的返回值,会传递给 p 的回调函数。
问题解答
1. Promise 有几种状态
pending(进行中)、fulfilled(已成功)和 rejected(已失败)
2. Promise 有什么优缺点
可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数;Promise 对象提供统一的接口,是的控制异常操作更加容易。
无法取消 Promise,一旦新建立即执行;若不设置回调函数,则 Promise 内部抛出的异常反应不到外部;pending 状态无法得知进展。
3. Promise 构造函数是同步还是异步执行,then 呢?
构造函数同步执行,then 异步执行
4. Promise 和 setTimeout 的区别
setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.then()在本轮“事件循环”结束时执行。
5. 如何实现 Promise.all
function promiseAll(promises) {return new Promise((resolve, reject) => {
let resultCount = 0;
let results = new Array(promises.length);
for (let i = 0; i < promises.length; i++) {promises[i].then(value => {
resultCount++;
results[i] = value;
if (resultCount === promises.length) {return resolve(results)
}
}, error => {reject(error)
})
}
})
}
let p1 = new Promise(resolve => resolve('p1'))
let p2 = new Promise(resolve => resolve('p2'))
let p3 = Promise.reject('p3 error')
Promise.all([p1, p2, p3]).then(results => {console.log(results)
}).catch(error => {console.log(error) // 'p3 error'
})
promiseAll([p1, p2]).then(results => {console.log(results) // ['p1', 'p2']
}).catch(error => {console.log(error)
})
6. 如何实现 Promise.finally
Promise.prototype.finally = function (callback) {
let P = this.constructor; // 构造函数
console.log(P);
return this.then(value => P.resolve(callback()).then(() => value), // resolve
reason => P.resolve(callback()).then(() => { throw reason}) // reject
);
};
参考文章
《ECMAScript 6 入门——阮一峰》