前言
面试中时常会出现需要手动实现某个功能的要求,所以我准备整理一个自己动手实现系列文章,这一次呢就是自己动手实现 promise
实现 promise 思路
基础步骤
- 设定三个状态
PENDING 、 FULFILLED 、 REJECTED ,只能由 PENDING 改变为 FULFILLED 、 REJECTED ,并且只能改变一次
MyPromise 接收一个函数 executor , executor 有两个参数 resolve 方法和 reject 方法
resolve 将 PENDING 改变为 FULFILLED
reject 将 PENDING 改变为 FULFILLED
promise 变为 FULFILLED 状态后具有一个唯一的 value
promise 变为 REJECTED 状态后具有一个唯一的 reason
** then 方法**
then 方法接受两个参数 onFulfilled 、 onRejected ,它们分别在状态由 PENDING 改变为 FULFILLED 、 REJECTED 后调用
- 一个
promise 可绑定多个 then 方法
then 方法可以同步调用也可以异步调用
- 同步调用:状态已经改变,直接调用
onFulfilled 方法
- 异步调用:状态还是
PENDING ,将 onFulfilled 、 onRejected 分别加入两个函数数组 onFulfilledCallbacks 、 onRejectedCallbacks ,当异步调用 resolve 和 reject 时,将两个数组中绑定的事件循环执行。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected';
function MyPromise(executor) { this.state = PENDING; this.value = null; this.reason = null;
this.onFulfilledCallbacks = []; this.onRejectedCallbacks = [];
const resolve = (value) => { if (this.state === PENDING) { this.state = FULFILLED; this.value = value;
this.onFulfilledCallbacks.forEach(func => { func(); }); } }
const reject = (reason) => { if (this.state === PENDING) { this.state = REJECTED; this.reason = reason; this.onRejectedCallbacks.forEach(func => { func(); }); } }
try { executor(resolve, reject); } catch (reason) { reject(reason); } }
MyPromise.prototype.then = function (onFulfilled, onRejected) { switch (this.state) { case FULFILLED: onFulfilled(this.value); break; case REJECTED: onFulfilled(this.value); break; case PENDING: this.onFulfilledCallbacks.push(() => { onFulfilled(this.value); }) this.onRejectedCallbacks.push(() => { onRejected(this.reason); }) break; }
|
then方法异步调用
如下面的代码:输入顺序是:1、2、ConardLi
1 2 3 4 5 6 7 8 9 10 11 12 13
|
console.log(1);
let promise = new Promise((resolve, reject) => { resolve('ConardLi'); });
promise.then((value) => { console.log(value); });
console.log(2);
|
虽然 resolve 是同步执行的,我们必须保证 then 是异步调用的,我们用 setTimeout 来模拟异步调用(并不能实现微任务和宏任务的执行机制,只是保证异步调用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
MyPromise.prototype.then = function (onFulfilled, onRejected) { if (typeof onFulfilled != 'function') { onFulfilled = function (value) { return value; } } if (typeof onRejected != 'function') { onRejected = function (reason) { throw reason; } } switch (this.state) { case FULFILLED: setTimeout(() => { onFulfilled(this.value); }, 0); break; case REJECTED: setTimeout(() => { onRejected(this.reason); }, 0); break; case PENDING: this.onFulfilledCallbacks.push(() => { setTimeout(() => { onFulfilled(this.value); }, 0); }) this.onRejectedCallbacks.push(() => { setTimeout(() => { onRejected(this.reason); }, 0); }) break; } }
|
then方法链式调用
保证链式调用,即 then 方法中要返回一个新的 promise ,并将 then 方法的返回值进行 resolve 。
注意:这种实现并不能保证 then 方法中返回一个新的 promise ,只能保证链式调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| MyPromise.prototype.then = function (onFulfilled, onRejected) { if (typeof onFulfilled != 'function') { onFulfilled = function (value) { return value; } } if (typeof onRejected != 'function') { onRejected = function (reason) { throw reason; } }
const promise2 = new MyPromise((resolve, reject) => { switch (this.state) { case FULFILLED: setTimeout(() => { try { const x = onFulfilled(this.value); resolve(x); } catch (reason) { reject(reason); } }, 0); break; case REJECTED: setTimeout(() => { try { const x = onRejected(this.reason); resolve(x); } catch (reason) { reject(reason); } }, 0); break; case PENDING: this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); resolve(x); } catch (reason) { reject(reason); } }, 0); }) this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); resolve(x); } catch (reason) { reject(reason); } }, 0); }) break; } }) return promise2; }
|
catch方法
若上面没有定义 reject 方法,所有的异常会走向 catch 方法:
1 2 3 4 5
|
MyPromise.prototype.catch = function(onRejected) { return this.then(null, onRejected); };
|
finally方法
不管是 resolve 还是 reject 都会调用 finally 。
1 2 3 4 5 6 7 8 9 10 11
|
MyPromise.prototype.finally = function(fn) { return this.then(value => { fn(); return value; }, reason => { fn(); throw reason; }); };
|
Promise.resolve
Promise.resolve 用来生成一个直接处于 FULFILLED 状态的 Promise 。
1 2 3 4 5 6
| MyPromise.reject = function(value) { return new MyPromise((resolve, reject) => { resolve(value); }); };
|
Promise.reject
Promise.reject 用来生成一个直接处于 REJECTED 状态的 Promise 。
1 2 3 4 5 6
| MyPromise.reject = function(reason) { return new MyPromise((resolve, reject) => { reject(reason); }); };
|
all方法
接受一个 promise 数组,当所有 promise 状态 resolve 后,执行 resolve
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| MyPromise.all = function (promises) { return new Promise((resolve, reject) => { if (promises.length === 0) { resolve([]); } else { let result = []; let index = 0; for (let i = 0; i < promises.length; i++) { promises[i].then(data => { result[i] = data; if (++index === promises.length) { resolve(result); } }, err => { reject(err); return; }); } } }); }
|
race方法
接受一个 promise 数组,当有一个 promise 状态 resolve 后,执行 resolve
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| MyPromise.race = function (promises) { return new Promise((resolve, reject) => { if (promises.length === 0) { resolve(); } else { let index = 0; for (let i = 0; i < promises.length; i++) { promises[i].then(data => { resolve(data); }, err => { reject(err); return; }); } } }); }
|
最后
如此一个自定义的 promise 就实现了,怎么样学回来吗?