一、动机
Promise 是目前处理异步操作中必不可少的内容,即使你使用了 async await ,但最后得到的还是个被 Promise 包裹的内容,例如:
因此,无论是在实际学习、工作或者面试中,都无法避免 Promise 的相关使用和原理,特别是在面试中甚至会让你自己实现一个 Promise. 本文主要介绍 Promise 的一些使用和特性,并使用自己的代码去实现它对应的功能,当然注重的应该是对实现过程的理解,而不是死记硬背!!!
二、Promise 前置知识
要想要深刻了解某个知识,前提条件是:你可以不是很明白其中原理,但是你必须知道如何正常使用?因此,建议对不了解的知识,首先得学会基本使用,然后在从使用层面去接触底层原理。
基本介绍
- Promise 实例拥有三个状态:【pending、fulfilled、rejected】. 并且这三种状态只能从 【pending --> fulfilled】 或 【pending --> rejected】, 也就是说只要当前状态不是 pending ,那么当前状态就不能被改变.
- 1. 实例化 Promise 时,可以接收一个函数作为参数,这个函数可以接收到 resolve 和 reject 两个实例方法,用于更改当前实例的状态,并把它们接收到的参数传递给下一个 then 对应的参数中.
- PS: Promise 中的回调是被同步执行的,但是 then 操作属于异步执行
- 2. then 方法可以接收两个函数作为参数,第一个函数相当于执行上一个 promise 中执行 resolve 后对应的回调,第二个函数相当于执行上一个 promise 中执行 reject 后对应的回调.
// 1. 实例化 Promise 时
// 可以接收一个函数作为参数,这个函数可以接收到 resolve 和 reject 两个实例方法
// 用于更改当前实例的状态,并把它们接收到的参数传递给下一个 then 对应的参数中
new Promise((resolve, reject) => {
// resolve 和 reject 可以都执行,但都执行的意义不大,因为 promise 状态发生更改后,就不能在被更改
resolve('ok');
// reject('err');
}).then((value) => {
console.log("resolve callback = ", value); // 若执行 resolve,则 value = ok
}, (reason) => {
console.log("reject callback = ", reason); // 若执行 reject,则 value = err
});
// 2. then 方法可以接收两个函数作为参数:
// 第一个函数相当于执行上一个 promise 中执行 resolve 后对应的回调
// 第二个函数相当于执行上一个 promise 中执行 reject 后对应的回调
- 3. 在 then 的两个回调函数中返回的值,默认可以被下一个 then 中的第一个回调函数接收到,其实表明了,then 操作之后会得到一个新的 promise,并且这个新的 promise 的状态默认 fulfilled.
// 3. 在 then 的两个回调函数中返回的值,默认可以被下一个 then 中的第一个回调函数接收到
// 其实表明了,then 操作之后会得到一个新的 promise,并且这个新的 promise 的状态默认 fulfilled
let p1 = new Promise((resolve, reject) => {
resolve('ok');
// reject('err');
});
let p2 = p1.then((value) => {
console.log("resolve p1.then = ", value); // ok
return 'then ok';
}, (reason) => {
console.log("reject p1.then = ", reason);// err
return 'then err';
})
p2.then((value) => {
console.log("resolve p2.then = ", value);// ok || err
}, (reason) => {
console.log("reject p2.then = ", reason);
});
- 4. then 中允许返回 Promise 实例,但不允许返回同一个 Promise 实例. 换句话说,不能在同一个 Promise 实例的 then 操作中返回它自己.
- 5. then 方法中只要设置了上一个 Promise 中 reject 对应的回调,那么就可以正常接收到错误信息,否则按 JavaScript 的报错机制显示.
// 4. then 中允许返回 Promise 实例,但不允许返回同一个 Promise 实例
// 换句话说,不能在同一个 Promise 实例的 then 操作中返回它自己
let p1 = new Promise((resolve, reject) => {
resolve('ok');
// reject('err');
});
let p2 = p1.then((value) => {
console.log("resolve p1.then = ", value); // ok
return p2;
}, (reason) => {
console.log("reject p1.then = ", reason);// err
return p2;
})
p2.then((value) => {
console.log("resolve p2.then = ", value);// ok || err
}, (reason) => {
console.log("reject p2.then = ", reason);// TypeError: Chaining cycle detected for promise #<Promise>
});
// 5. then 方法中只要设置了上一个 Promise 中 reject 对应的回调,那么就可以正常接收到错误信息,否则按 JavaScript 的报错机制显示.
-
- Promise.all() 以数组形式接收多个 Promise ,当所有的 Promise 执行完成,且状态都为 fulfilled 时,将他们的执行结果以数组形式返回给下一个 then 操作中的 第一个函数回调,否则将发生错误的 Promise 结果,返回第二个函数回调.
// 1. p1 p2 都成功
let p1 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('p1 success');
},1000);
});
let p2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('p2 success');
// reject('p2 fail');
},2000);
});
Promise.all([p1,p2])
.then(value => {
console.log('all promise success = ', value); // all promise success = (2) ["p1 success", "p2 success"]
},reason => {
console.log('one promise fail = ', reason);
});
// 2. p1 成功 p2 失败
let p1 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('p1 success');
},1000);
});
let p2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
// resolve('p2 success');
reject('p2 fail');
},2000);
});
Promise.all([p1,p2])
.then(value => {
console.log('all promise success = ', value);
},reason => {
console.log('one promise fail = ', reason);// one promise fail = p2 fail
});
-
- Promise.race() 以数组形式接收多个 Promise ,只要有一个 Promise 先执行完成,无论什么状态,都以这个结果返回给下一个 then 中对应的回调函数.
let p1 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('p1 success');
// reject('p1 fail');
}