手写简易Promise+常用API

基本Promise类

  1. 属性:state,value和reason
  2. 转变状态:resolve和reject
  3. promise中有隐式try…catch调用
  4. then方法
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECT = 'REJECT'

class MyPromise {
    constructor(executor) {
        this.state = undefined
        this.value = undefined
        this.reason = undefined
        
        const resolve = val => {
            if (this.state === PENDING) {
                this.state = FULFILLED
                this.value = val
            }
        }

        const reject = reason => {
            if (this.state === PENDING) {
                this.state = REJECT
                this.reason = reason
            }
        }
        try {
            executor()
        } catch(err) {
            reject(err)
        }
    }
    then(onResolve, onReject) {
        if (this.state === FULFILLED) {
            onResolve(this.val)
        } 
         if (this.state === REJECT) {
            onReject(this.reason)
        }
    }
}

扩展then方法

then的异步调用

调用then方法时,若状态还在PENDING,则先将onResolve和onReject放进回调队列,FULFILLED/REJECT后执行并清空相应队列。

class MyPromise {
    constructor(executor) {
        ...
        this.onFulfilledCallbacks = []
        this.onRejectCallbacks = []

        const resolve = val => {
            if (this.state === PENDING) {
               ···
                this.onRejectCallbacks.forEach(cb => cb())
            }
        }

        const reject = reason => {
            if (this.state === PENDING) {
                ···
                this.onRejectCallbacks.forEach(cb => cb())
            }
        }
        try {
            executor()
        } catch(err) {
            reject(err)
        }
    }
    then(onResolve, onReject) {
        ···
        if (this.state === PENDING) {
            this.onFulfilledCallbacks.push(() => onResolve(this.value))
            this.onRejectCallbacks.push(() => onReject(this.value))
        }
    }

}

then的链式调用

then方法需返回新的Promise对象,方可继续链式调用。将then中的逻辑包装成新的Promise对象并返回,其中若是发生错误,直接reject

then(onFulfilled, onRejected) {
  const promiseInst = new MyPromise((resolve, reject) => {
      if (this.state === FULFILLED) {
        try {
          onFulfilled(this.value);
        } catch (err) {
          reject(err);
        }
      }

      if (this.state === REJECT) {
          try {
            onRejected(this.reason);
          } catch (err) {
            reject(err);
          }
      }

      if (this.state === PENDING) {
        this.onFulfilledCallbacks.push(() => {
            try {
              onFulfilled(this.value);
            } catch (err) {
              reject(err);
            }
        });
        this.onRejectedCallbacks.push(() => {
            try {
              onRejected(this.reason);
            } catch (err) {
              reject(err);
            }
        });
      }
    });

    return promiseInst;
  }

Promise.all

接收由promise对象组成的数组(可迭代对象即可),当所有promise都resolve时,它才会resolve,结果数组成为它的结果(元素顺序与对象在数组中的顺序相同,不管所花费的时间顺序);
当任意一个promise被reject时,新promise立刻reject,带有error就是被reject的error,其他promise仍会执行,但是它们的状态及结果都会被忽略。

Promise.prototype.all = function(promiseArr) {
    if (!isIterable(promiseArr)) {// 判断是否可以迭代
        throw new Error()
    }
    let valueArr = [], len = promiseArr.length, storedArrNum = 0
    if (len === 0) return Promise.resolve([])
    
    return new Promise((resolve, reject) => {
        if (isPromise(promise)) {
                promise.then(value => putInValueArr(value, idx, resolve), reject)
            } else {
                putInValueArr(promise, idx, resolve)
            }
    })

    function putInValueArr(value, idx, resolve) {
        valueArr[idx] = value
        if (++storedArrNum === len) {
            resolve(valueArr)
        }
    }
}

function isIterable(obj) {
    if (obj !== null && obj !== undefined && typeof obj[Symbol.iterator] === 'function') {
        return true
    }
    return false
}
function isPromise(promise) {
    if (promise == null || promise === undefined) return false
    if (typeof promise.then === 'function') return true
}

Promise.allSettled

不管接收的数组中promise都状态如何,只要都settled了,就返回一个由{status,value/reason}对象组成的数组。

allSettled(promiseArr) {
        if (!isIterable(promiseArr)) {
            throw new Error()
        }
        let valueArr = [], len = promiseArr.length, storedArrNum = 0
        if (len === 0) {
            return MyPromise.resolve([])
        }
        return new Promise((resolve) => {
            promiseArr.forEach((promise, idx) => {
                if (isPromise(promise)) {
                    promise.then(val => putInValueArr(FULFILLED, val, idx, resolve), reason => putInValueArr(REJECT, reason, idx, resolve))
                } else {
                    putInValueArr(promise, FULFILLED, idx, resolve)
                }
            })
        })

        function putInValueArr(status, val, idx, resolve) {
            switch (status) {
                case FULFILLED: {
                    valueArr[idx] = {
                        status,
                        value: val
                    }
                }
                case REJECT: {
                    valueArr[idx] = {
                        status,
                        reason: val
                    }
                }
            }
            if (++storedArrNum === len) {
                resolve(valueArr)
            }
        }
    }

Promise.race

只返回最先settled的promise结果:value/reason

race(promiseArr) {
        if (!isIterable(promiseArr)) {
            throw new Error()
        }
        let len = promiseArr.length
        if (len === 0) promise.resolve([])
        return new Promise((resolve, reject) => {
            promiseArr.forEach(promise => {
                if (isPromise(promise)) {
                    promise.then(val => resolve(val), reason => reject(reason))
                } else {
                    resolve(promise)
                }
            })
        })
    }

Promise.finally

不管链前promise状态如何,finally做常规工作(清理、扫尾),并将前面的状态通过promise链传递。

finally(finallyCB) {
      return this.then(value => new Promise.resolve(finallyCB()).then(() => value),
      reason => new Promise.resolve(finallyCB()).then(() => {throw reason}))
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值