一、Promise函数体执行顺序
调用resolve或reject并不会终结 Promise 的参数函数的执行。
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
// 2
// 1
● 上面代码中,调用resolve(1)
以后,后面的console.log(2)
还是会执行,并且会首先打印出来。这是因为立即 resolved
的 Promise
是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
● 一般来说,调用resolve
或reject
以后,Promise
的使命就完成了,后继操作应该放到then
方法里面,而不应该直接写在resolve
或reject
的后面。所以,最好在它们前面加上return
语句,这样就不会有意外。
new Promise((resolve, reject) => {
return resolve(1);
// 后面的语句不会执行
console.log(2);
})
二、Promise实例作为resolve入参
● 如果调用resolve
函数和reject
函数时带有参数,那么它们的参数会被传递给回调函数。
● reject
函数的参数通常是Error
对象的实例,表示抛出的错误;
● resolve
函数的参数除了正常的值以外,还可能是另一个 Promise
实例,比如像下面这样。
const p1 = new Promise(function (resolve, reject) {
// ...
});
const p2 = new Promise(function (resolve, reject) {
// ...
resolve(p1); // -----> 入参为Promise实例p1
})
● 上面代码中,p1
和p2
都是 Promise
的实例,但是p2
的resolve
方法将p1
作为参数,即一个异步操作的结果是返回另一个异步操作。【p1
作为 异步操作的结果】
● 注意,这时p1
的状态就会传递给p2
,也就是说,p1
的状态决定了p2
的状态。如果p1
的状态是pending
,那么p2
的回调函数就会等待p1
的状态改变;如果p1
的状态已经是resolved
或者rejected
,那么p2
的回调函数将会立刻执行。
var p1 = new Promise (function (resolve, reject) {
setTimeout(function () {
reject (new Error("fail"));
}, 3000);
})
var p2 = new Promise (function (resolve, reject) {
setTimeout(function () {
resolve(p1)
}, 1000);
})
p2.then(function (result) {
console.log(result);
}).catch(function (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
方法指定的回调函数。