Promise原理

105 阅读2分钟

一、实现思路

  1. Promise就是一个类,在执行这个类的时候,需要传递一个执行器进去,执行器会立即执行。
  2. Promise中有三个状态,分别为成功fulfilled、失败rejected、等待pending, pending => fulfilled、pending => rejected, 一旦状态确定就不可更改。
  3. resolve和reject函数是用来更改状态的。
  4. then方法内部做的事情就是判断状态。如果状态是成功,调用成功的回调函数;如果状态是失败,调用失败的回调函数。
  5. then成功回调有一个参数,表示成功之后的值;then失败回调有一个参数,表示失败之后的原因。
  6. then等待的时候,将成功回调和失败回调存储起来。resolve和reject函数分别调用存储的成功回调和失败回调。
  7. then方法是可以链式调用的,后面then方法的回调函数拿到的值是上一个then方法的回调函数的返回值。

二、Promise核心代码实现

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
    status = PENDING
    sucessCallbacks = []
    failCallbacks = []
    value = undefined
    reason = undefined

    constructor(executor) {
        executor(this.resolve, this.reject)
    }
    
    resolve(value) {
        if(this.status === PENDING) return
        this.status = FULFILLED
        while(this.sucessCallbacks && this.sucessCallbacks.length) this.sucessCallbacks.shift(value)
    }
    
    reject(reason) {
            if(this.status === PENDING) return
        this.status = REJECTED
        while(this.failCallbacks && this.failCallbacks.length) this.failCallbacks.shift(reason)
    }
    }
    
    then(sucessCallback, failCallback) {
        if(this.status === FULFILLED) {
            sucessCallback(this.value)
        } else if(this.status === REJECTED) {
            failCallback(this.reason)
        } else {
            sucessCallback && this.sucessCallbacks.push(sucessCallback)
            failCallback && this.failCallbacks.push(failCallback)
        }
    }
}

三、Promise.all()方法代码实现

class MyPromise {
    ....
    
    static all(array) {
        let result = []
        let index = 0
        
        return new MyPromise((resolve, reject) => {
            function addData(key, value) {
                result[key] = value
                index++
                if(index === array.length) {
                    resolve(result)
                }
            }
            
            for(let i=0; i<array.length; i++) {
                let current = array[i]
                if(current instanceof MyPromise) {
                    // promise值
                    current.then(value => addData(value), reason => reject(reason))
                } else {
                    // 普通值
                    addData(i, current)
                }
            }
        })
    }
}

三、判断抛出的异常是第几个promise错误

在 Promise 被 reject 时返回一个包含唯一标识属性的对象,以便在处理错误时可以确定是哪个 Promise 出了问题。

function createPromiseWithId(id) { 
    return new Promise((resolve, reject) => { 
        // 在这里执行异步操作 
        // 如果出现错误,将包含唯一标识的对象传递给 reject 方法 
        reject({ id: id, message: 'Error occurred' }); 
    }); 
} 

const promises = [ 
    createPromiseWithId(1), 
    createPromiseWithId(2), 
    createPromiseWithId(3) 
]; 

Promise.all(promises).then(results => { 
    console.log(results); 
}).catch(error => { 
    console.log('Promise with id ' + error.id + ' failed: ' + error.message); 
});