课程目标
- 了解PromiseA+规范
- 实现一个简单的Promise
知识要点
- Promise的三种状态
- Promise的then方法
- resolvePromise
- onFulfilled和onRejected
补充知识点
PromiseA+
- promise 是一个有 then 方法的对象或函数
- thenable 是一个有 then 方法的对象或函数
- value 是 promise 状态成功时的值,也就是 resolve 的参数,包括各种数据类型,也包括undefined/thenable或者是 promise
- reason 是 promise 状态失败时的值, 也就是 reject 的参数,表示拒绝的原因
- exception 是一个使用throw抛出的异常值
规范
三种状态
promise有三种状态,pending、fulfilled、rejected。 其中 pending 为初始状态,fulfilled和rejected为最终态
一个 promise 被 resolve 之后变成 fulfilled 状态,必须拥有一个 value 值 一个 promise 被 rejected 之后变成 rejected 状态,必须拥有一个 reason 值
即 pending -> resolve(value) -> fulfilled
pending -> reject(reason) -> rejected
then
Promise.then(onFulfilled, onRejected)
promise 提供一个 then 方法用来访问最终结果,无论是 value 还是 reason
-
参数要求
1.1 onFullfilled 和 onRejected 必须是函数,否则被忽略。
-
onFulfilled 特性
2.1 在 promise 变成 fulfilled 时,调用 onFulfilled,参数是 value
2.2 在 promise 变成 fulfilled 之前,不应该调用
2.3 只能调用一次
-
onRejected 特性
3.1 在 promise 变成 rejected 时,调用 onRejected,参数是 reason
3.2 在 promise 变成 rejected 之前,不应该调用
3.3 只能调用一次
-
onFulfilled 和 onRejected 应该为微任务,用 queueMicrotask 实现。
-
then 方法可以被调用多次
5.1 promise状态变成 fulfilled 后,所有的 onFulfilled 回调都需要按照then的顺序执行, 也就是按照注册顺序执行
5.2 promise状态变成 rejected 后,所有的 onRejected 回调都需要按照then的顺序执行, 也就是按照注册顺序执行
-
返回值
promise2 = promise1.then(onFulfilled, onRejected)6.1 onFulfilled 或 onRejected 执行的结果为x,调用 resolvePromise
6.2 如果 onFulfilled 或者 onRejected 执行时抛出异常,promise2需要被reject
6.3 如果 onFulfilled 不是一个函数,promise2 以 promise1 的 value 触发fulfilled
6.4 如果 onRejected 不是一个函数,promise2 以 promise1 的reason 触发rejected
-
resolvePromise
resolvePromise(promise2, x, resolve, reject)7.1 如果 promise2 和 x 相等,那么 reject TypeError
7.2 如果 x 是一个 promsie
x 是 pending 态,那么 promise 必须要在 pending,直到 x 变成 fulfilled or rejected.
x 被 fulfilled, fulfill promise with the same value.
x 被 rejected, reject promise with the same reason.
7.3 如果 x 是一个 object 或者是一个 function
let then = x.thenx.then 这步出错,那么 reject promise with e as the reason
then 是一个函数,then.call(x, resolvePromiseFn, rejectPromise)
resolvePromiseFn 的 入参是 y,执行 resolvePromise(promise2, y, resolve, reject);
rejectPromise 的 入参是 r,reject promise with r
如果 resolvePromise 和 rejectPromise 都调用了,那么第一个调用优先,后面的调用忽略。
如果调用then抛出异常,resolvePromise 或 rejectPromise 已经被调用,那么忽略。否则 reject promise with e as the reason
如果 then 不是一个 function,fulfill promise with x
代码实现
// 定义promise类及初始状态 const PENDING = "pending"; const FULLFILLED = "fullfilled"; const REJECTED = "rejected"; class MyPromise { // 保存pending状态成功或失败的回调 FULLFILLED_CALLBACK_LIST = []; REJECTED_CALLBACK_LIST = []; _status = PENDING; constructor(fn) { this.status = PENDING; this.value = null; this.reason = null; try { fn(this.resolve.bind(this), this.reject.bind(this)); } catch (e) { this.reject(e); } } resolve(value) { if (this.status == PENDING) { this.value = value; this.status = FULLFILLED; } } reject(reason) { if (this.status == PENDING) { this.reason = reason; this.status = REJECTED; } } get status() { return this._status; } set status(newStatus) { this._status = newStatus; switch (newStatus) { case FULLFILLED: { this.FULLFILLED_CALLBACK_LIST.forEach((callback) => { callback(this.value); }); } break; case REJECTED: { this.REJECTED_CALLBACK_LIST.forEach((callback) => { callback(this.reason); }); } break; } } // then接收两个参数, onFulfilled 和 onRejected then(onFulfilled, onRejected) { // 如果接收的不是function就忽略,忽略指的是原样返回 value 或者 reason. const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value; }; const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason; }; // then 整体返回一个promise // 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e // 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行 resolvePromise 方法 const promise2 = new MyPromise((resolve, reject) => { const fulfilledMicrotask = () => { try { const x = realOnFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }; const rejectedMicrotask = () => { try { const x = realOnRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }; switch (this.status) { case FULLFILLED: fulfilledMicrotask(); break; case REJECTED: rejectedMicrotask(); break; case PENDING: // pending状态暂时存入数组中,等待状态改变再回调 this.FULLFILLED_CALLBACK_LIST.push(fulfilledMicrotask); this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask); break; } }); return promise2; } resolvePromise(promise2, x, resolve, reject) { // 如果 promise2 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise if (promise2 === x) { return reject( new TypeError("The promise and the return value are the same") ); } if (x instanceof MyPromise) { // 如果x是promise,继续执行x,如果执行的时候得到一个y,继续解析y queueMicrotask(() => { x.then((y) => { this.resolvePromise(promise2, y, resolve, reject); }, reject); }); } else if (typeof x == "object" || this.isFunction(x)) { // 如果x是对象或函数 if (x === null) { return resolve(x); } let then = null; try { then = x.then; } catch (e) { return reject(e); } // 如果then是函数 if (this.isFunction(then)) { let called = false; try { then.call( x, (y) => { if (called) return; called = true; this.resolvePromise(promise2, y, resolve, reject); }, (r) => { if (called) return; called = true; reject(r); } ); } catch (e) { if (called) return; reject(e); } } else { resolve(x); } } else { resolve(x); } } // 判断是否是一个函数 isFunction(param) { return typeof param === "function"; } }