xianzao / xianzao-interview

前端 每日一道面试题
64 stars 4 forks source link

【2022.11.23】手写Promise #3

Open xianzao opened 1 year ago

xianzao commented 1 year ago

实现Promise的基本功能及常见方法

xianzao commented 1 year ago
  1. 基础resolve 与 reject

    class MyPromise {
    // 构造方法
    constructor(executor) {
    // 初始化值
    this.initValue();
    // 初始化this指向
    this.initBind();
    // 执行传进来的函数
    try {
      // 执行传进来的函数
      executor(this.resolve, this.reject);
    } catch (e) {
      // 捕捉到错误直接执行reject
      this.reject(e);
    }
    }
    
    initBind() {
    // 初始化this
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
    }
    
    initValue() {
    // 初始化值
    this.PromiseResult = null; // 终值
    this.PromiseState = 'pending'; // 状态
    }
    
    resolve(value) {
    // state是不可变的
    if (this.PromiseState !== 'pending') return;
    // 如果执行resolve,状态变为fulfilled
    this.PromiseState = 'fulfilled';
    // 终值为传进来的值
    this.PromiseResult = value;
    }
    
    reject(reason) {
    // state是不可变的
    if (this.PromiseState !== 'pending') return;
    // 如果执行reject,状态变为rejected
    this.PromiseState = 'rejected';
    // 终值为传进来的reason
    this.PromiseResult = reason;
    }
    }
  2. then的实现

    
    then(onFulfilled, onRejected) {
    // 接收两个回调 onFulfilled, onRejected
    
    // 参数校验,确保一定是函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
    
    var thenPromise = new MyPromise((resolve, reject) => {
    
        const resolvePromise = cb => {
            try {
                const x = cb(this.PromiseResult)
                if (x === thenPromise) {
                    // 不能返回自身哦
                    throw new Error('不能返回自身。。。')
                }
                if (x instanceof MyPromise) {
                    // 如果返回值是Promise
                    // 如果返回值是promise对象,返回值为成功,新promise就是成功
                    // 如果返回值是promise对象,返回值为失败,新promise就是失败
                    // 谁知道返回的promise是失败成功?只有then知道
                    x.then(resolve, reject)
                } else {
                    // 非Promise就直接成功
                    resolve(x)
                }
            } catch (err) {
                // 处理报错
                reject(err)
                throw new Error(err)
            }
        }
    
        if (this.PromiseState === 'fulfilled') {
            // 如果当前为成功状态,执行第一个回调
            resolvePromise(onFulfilled)
        } else if (this.PromiseState === 'rejected') {
            // 如果当前为失败状态,执行第二个回调
            resolvePromise(onRejected)
        } else if (this.PromiseState === 'pending') {
            // 如果状态为待定状态,暂时保存两个回调
            // 如果状态为待定状态,暂时保存两个回调
            this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
            this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
        }
    })
    
    // 返回这个包装的Promise
    return thenPromise

}


3. all的实现

- 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
- 如果所有Promise都成功,则返回成功结果数组
- 如果有一个Promise失败,则返回这个失败结果

```js
static all(promises) {
    const result = []
    let count = 0
    return new MyPromise((resolve, reject) => {
        const addData = (index, value) => {
            result[index] = value
            count++
            if (count === promises.length) resolve(result)
        }
        promises.forEach((promise, index) => {
            if (promise instanceof MyPromise) {
                promise.then(res => {
                    addData(index, res)
                }, err => reject(err))
            } else {
                addData(index, promise)
            }
        })
    })
}
  1. race的实现
static race(promises) {
    return new MyPromise((resolve, reject) => {
        promises.forEach(promise => {
            if (promise instanceof MyPromise) {
                promise.then(res => {
                    resolve(res)
                }, err => {
                    reject(err)
                })
            } else {
                resolve(promise)
            }
        })
    })
}
  1. allSettled的实现
static allSettled(promises) {
    return new Promise((resolve, reject) => {
        const res = []
        let count = 0
        const addData = (status, value, i) => {
            res[i] = {
                status,
                value
            }
            count++
            if (count === promises.length) {
                resolve(res)
            }
        }
        promises.forEach((promise, i) => {
            if (promise instanceof MyPromise) {
                promise.then(res => {
                    addData('fulfilled', res, i)
                }, err => {
                    addData('rejected', err, i)
                })
            } else {
                addData('fulfilled', promise, i)
            }
        })
    })
}
  1. any的实现
static any(promises) {
    return new Promise((resolve, reject) => {
        let count = 0
        promises.forEach((promise) => {
            promise.then(val => {
                resolve(val)
            }, err => {
                count++
                if (count === promises.length) {
                    reject(new AggregateError('All promises were rejected'))
                }
            })
        })
    })
}