PromiseA+规范
- promise 是一个有then方法的对象或者是函数
- thenable 是一个有then方法的对象或者是函数
- value 是promise状态成功时的值,也就是resolve的参数, 包括各种数据类型, 也包括undefined/thenable或者是 promise
- reason 是promise状态失败时的值, 也就是reject的参数, 表示拒绝的原因
- exception 是一个使用throw抛出的异常值
Promise States
promise应该有三种状态. 要注意他们之间的流转关系.
-
pending
1.1 初始的状态, 可改变. 1.2 一个promise在resolve或者reject前都处于这个状态。
1.3 可以通过 resolve -> fulfilled 状态;
1.4 可以通过 reject -> rejected 状态;
-
fulfilled
2.1 最终态, 不可变.
2.2 一个promise被resolve后会变成这个状态.
2.3 必须拥有一个value值
-
rejected
3.1 最终态, 不可变. 3.2 一个promise被reject后会变成这个状态 3.3 必须拥有一个reason
Tips: promise的状态流转
pending -> resolve(value) -> fulfilled
pending -> reject(reason) -> rejected
then
promise应该提供一个then方法, 用来访问最终的结果, 无论是value还是reason.
promise.then(onFulfilled, onRejected)
-
参数要求
1.1 onFulfilled 必须是函数类型, 如果不是函数, 应该被忽略.
1.2 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的顺序执行, 也就是按照注册顺序执行(所以在实现的时候需要一个数组来存放多个onFulfilled的回调)
5.2 promise状态变成 rejected 后,所有的 onRejected 回调都需要按照then的顺序执行, 也就是按照注册顺序执行(所以在实现的时候需要一个数组来存放多个onRejected的回调)
-
返回值
then 应该返回一个promise
promise2 = promise1.then(onFulfilled, onRejected);6.1 onFulfilled 或 onRejected 执行的结果为x, 调用 resolvePromise( 这里大家可能难以理解, 可以先保留疑问, 下面详细讲一下resolvePromise是什么东西 )
6.2 如果 onFulfilled 或者 onRejected 执行时抛出异常e, promise2需要被reject
6.3 如果 onFulfilled 不是一个函数, promise2 以promise1的value 触发fulfilled
6.4 如果 onRejected 不是一个函数, promise2 以promise1的reason 触发rejectet
-
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.then. 如果 x.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抛出异常e 如果 resolvePromise 或 rejectPromise 已经被调用,那么忽略 则,reject promise with e as the reason 如果 then 不是一个function. fulfill promise with x.
实现一个 promise
-
定义 Mpromise 类 及 三种状态
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; class Mpromise { constructor() } -
设置初始状态
class Mpromise { constructor() { this.status = PENDING; this.value = null; this.reason = null; } } -
resolve 和 reject 方法
class Mpromise { constructor() { this.status = PENDING; this.value = null; this.reason = null; } resolve(value) { if (this.status === PENDING) { this.value = value; this.status = FULFILLED; } } reject(reason) { if (this.status === PENDING) { this.reason = reason; this.status = REJECTED; } } } -
promise 形参
new Promise((resolve, reject) => {});- 接收参数是一个函数,函数接收 resolve 和 reject 两个参数
- new Promise 的时候就要执行这个函数 ,如果执行出现任何报错,都要 reject 出去
class Mpromise { constructor() { this.status = PENDING; this.value = null; this.reason = null; try { fn(this.resolve.bind(this), this.reject.bind(this)); } catch (error) { this.reject(error); } } } -
then 方法
then(onFulfilled, onRejected);-
then 接收两个参数 onFulfilled 和 onRejected
-
处理参数,如果不是函数,包装成函数远洋返回 value 或者 reason
isFunction(param) { return typeof param === 'function'; } then(onFulfilled,onRejected){ const realOnFufilled = this.isFunction(onFulfilled)?onFulfilled:(value)=>{ return value; } const realOnRejected = this.isFunction(onRejected)?onRejected:(reason)=>{ throw reason; } } -
then 方法整体返回一个新的 promise
then(onFulfilled,onRejected){ const realOnFufilled = this.isFunction(onFulfilled)?onFulfilled:(value)=>{ return value; } const realOnRejected = this.isFunction(onRejected)?onRejected:(reason)=>{ throw reason; } const promise2 = new MPromise((resolve,reject)=>{}); return promise2; } -
根据当前 promise 的状态 调用不同的函数
then(onFulfilled,onRejected){ const realOnFufilled = this.isFunction(onFulfilled)?onFulfilled:(value)=>{ return value; } const realOnRejected = this.isFunction(onRejected)?onRejected:(reason)=>{ throw reason; } const promise2 = new MPromise((resolve,reject)=>{ switch(this.status){ case FULFILLED:{ realOnFufilled(this.value); break; } case REJECTED:{ realOnRejected(this.reason); break; } } }); return promise2; } -
如果是异步,then 方法执行的时候可能还是 pending 状态,这时候就执行不到回调,所以我们需要监听 status ,当状态变为 fulfilled 或者 rejected 时,去执行 callback
-
then 执行的时候如果是 pending ,则将 callback 存用数组起来,状态改变时 按顺序执行
FULFILLED_CALLBACK_LIST = []; REJECTED_CALLBACK_LIST = []; then(onFulfilled,onRejected){ const realOnFufilled = this.isFunction(onFulfilled)?onFulfilled:(value)=>{ return value; } const realOnRejected = this.isFunction(onRejected)?onRejected:(reason)=>{ throw reason; } const promise2 = new MPromise((resolve,reject)=>{ switch(this.status){ case FULFILLED:{ realOnFufilled(this.value); break; } case REJECTED:{ realOnRejected(this.reason); break; } case PENDING:{ FULFILLED_CALLBACK_LIST.push(realOnFufilled); REJECTED_CALLBACK_LIST.push(realOnRejected); } } }); return promise2; } -
在 status 发生改变的时候去执行回调,这里使用 es6 的 getter 和 setter 监听
_status = PENDING; get status(){ return this._status; } set status(newStatus){ switch (newStatus){ case FULFILLED:{ this.FULFILLED_CALLBACK_LIST.forEach(callback=>{ callback(this.value); }) } case REJECTED:{ this.REJECTED_CALLBACK_LIST.forEach(callback=>{ callback(this.reason); }) } } }
-
-
-
then 的返回值
then 的返回值是一个 Promise, 那么接下来具体讲一下返回 promise 的 value 和 reason 是什么.
-
如果 onFulfilled 或 onRejected 抛出异常 error ,则promise2必须拒绝执行并返回原因(手动catch,报错就reject)
then(onFulfilled,onRejected){ const realOnFufilled = this.isFunction(onFulfilled)?onFulfilled:(value)=>{ return value; } const realOnRejected = this.isFunction(onRejected)?onRejected:(reason)=>{ throw reason; } const promise2 = new MPromise((resolve,reject)=>{ const fulfilledMicrotask = ()=>{ try{ realOnFufilled(this.value); }catch(error){ reject(error); } } const rejectedMicrotask = ()=>{ try{ realOnRejected(this.reason); }catch(error){ reject(error); } } switch(this.status){ case FULFILLED:{ fulfilledMicrotask(); break; } case REJECTED:{ rejectedMicrotask(); break; } case PENDING:{ FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask); REJECTED_CALLBACK_LIST.push(rejectedMicrotask); } } }); return promise2; } -
如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
-
如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因。
需要注意的是,如果promise1的onRejected执行成功了,promise2应该被resolve
const realOnFulfilled = this.isFunction(onFufilled)?onFufilled:(value)=>{ return value; } const realOnRejected = this.isFunction(onRejected)?onRejected:(reason)=>{ throw reason; }- 如果 onFufilled 或者 onRejected 返回一个值 x ,则执行resolvePromise()
then(onFulfilled,onRejected){ const realOnFufilled = this.isFunction(onFulfilled)?onFulfilled:(value)=>{ return value; } const realOnRejected = this.isFunction(onRejected)?onRejected:(reason)=>{ throw reason; } const promise2 = new MPromise((resolve,reject)=>{ const fulfilledMicrotask = ()=>{ try{ const x = realOnFufilled(this.value); this.resolvePromise(promise2,x,resolve,reject); }catch(error){ reject(error); } } const rejectedMicrotask = ()=>{ try{ const x = realOnRejected(this.reason); this.resolvePromise(promise2,x,resolve,reject); }catch(error){ reject(error); } } switch(this.status){ case FULFILLED:{ fulfilledMicrotask(); break; } case REJECTED:{ rejectedMicrotask(); break; } case PENDING:{ FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask); REJECTED_CALLBACK_LIST.push(rejectedMicrotask); } } }); return promise2; }
-
-
resolvePromise 方法
resolvePromise(promise2,x,resolve,reject){ // 如果传入的新promise 和 x指向同一个对象,以TypeError拒绝执行新的promise,避免死循环 if(promise2 === x){ return reject(new TypeError('promise和返回值不能相等')) } // x 如果是一个promise,则使 newPromise 接受 x 的状态 // 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y if(x instansof MPromise){ queueMicrotask(()=>{ x.then((y)=>{ this.resolvePromise(promise2,y,resolve,reject); },reject) }) }else if(typeof x === 'object' || this.isFunction(x)){ // 如果 x 为对象或者函数 if(x === null){ // null也会被判为对象 return resolve(x); }else{ let then = null; try{ //防止x.then报错 then = x.then; }catch(error){ return reject(error) } if(isFunction(then)){ try{ then.call( x, (y)=>{ this.resolvePromise(promise2,y,resolve,reject); }, (r)=>{ reject(r) } ) }catch(error){ reject(error) } }else{ // then不是函数,以 x 为参数执行 promise resolve(x); } } }else{ // 如果 x 不为对象或者函数,以 x 为参数执行 promise resolve(x); } } -
其他方法
- race 接收一个存放promise的数组 返回最先执行完成的那个promise的结果
MPromise.race = function(promiseList){ return new MPromise((resolve, reject) => { const length = promiseList.length; if (length === 0) { resolve(); } else { for (let i = 0; i < promiseList.length; i++) { MPromise.resolve(promiseList[i]) .then(value => { return resolve(value); }) .catch(reason => { return reject(reason); }); } } }); }- all方法 接收一个存放promise的数组 按顺序(数组)返回所有promise的结果 如果某个promise被 reject 则整个结果为reject
MPromise.all = function(promiseList){ return new MPromise((resolve, reject) => { let valueList = []; let count = 0; for (let i = 0; i < promiseList.length; i++) { MPromise.resolve(promiseList[i]) .then(value => { // 不能使用push 保证顺序 valueList[i] = value; // if(valueList.length === length){ 这么写会出现 索引1先赋值,索引0未赋值,这时数组长度已经是2 // return resolve(valueList); // } // 正确做法 定义一个计数器 count++; if (count === promiseList.length) { resolve(valueList); } }) .catch(reason => { reject(reason); }); } }); }- finally 方法 接收一个回调 不管promise是resolve还是reject 都去执行回调
MPromise.prototype.finally = function(callback){ return this.then( value=>{ return MPromise.resolve(callback()).then(()=>value); }, err=>{ return MPromise.resolve(callback()).then(()=>{throw err}); } ) }