• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

模拟promise

武飞扬头像
hello9307
帮助1

基础逻辑

  1. 创建 promise 实例
  2. 创建 resolve、reject 更新状态
  3. 创建 then 方法,能够在状态变更后执行相应的承诺时事件
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise{
    /*
    * 创建 promise 实例时立即执行的方法
    * 通过构造函数传入一个执行函数,在 new promise((resolve, reject) => {}) 是就能立即执行这个函数
    * 将 resolve reject 通过参数传给执行函数,执行函数中使用者实际情况出发 promise 更新状态。
    */
    constructor(executor){
        executor(this.resolve, this.reject);
    }

    status = PENDING;
    value = '';
    reason = '';
    successCallbacks = [];
    failCallbacks = [];
    
    /*
    * 将状态变更为成功
    * 1.主要做3件事:1)更新状态为成功,2)保存成功的值,3)执行承诺事件
    * 2.因为这个方法是使用者触发的,所以这里使用箭头函数定义,这样this就能指向promise实例
    */
    resolve = value => {
        if(this.status !== PENDING) return; // 状态一旦变更就固定了
        this.status = FULFILLED;
        this.value = value;
        while (this.successCallbacks.length){
            this.successCallbacks.shift()(this.value);
        }
    }
    
    /*
    * 将状态变更为失败
    * 1.主要做3件事:1)更新状态为失败,2)保存失败原因,3)执行承诺事件
    */
    reject = reason => {
        if(this.status !== PENDING) return;
        this.status = REJECTED;
        this.reason = reason;
        while (this.failCallbacks.length){
            this.failCallbacks.shift()(this.value);
        }
    }

    /*
    * 承诺状态变更后要执的事件
    * 1.根据状态,执行相应的成功还是失败回调
    * 2.如果当前状态是 pendding,那么就保存成功失败回调,等转态变更后再执行
    */
    then(successCallback, failCallback){
        if(this.status === FULFILLED){  // 立即未异步执行 resolve 
            successCallback(this.value);
        }else if(this.status === REJECTED){
            failCallback(this.reason);
        }else if(this.status === PENDING){
            this.successCallbacks.push(successCallback);
            this.failCallbacks.push(failCallback);
        }
    }
}

增加链式调用

也就是实现 p.then().then() 这种情况,做法就是 then 方法返回一个新的 promise

  1. 返回一个新的 promise
  2. 用上个 promise 回调返回值更新为当前 promise 的 value
  3. 回调返回是个 promise 处理
then(successCallback, failCallback){
    // 参数可选,这样上个 then 参数为空,也会将上个结果保存到当前 promise
    successCallback = successCallback ? successCallback : value => value;
    failCallback = failCallback ? failCallback: reason => { throw reason };
    
    let p2 = new MyPromise((resolve, reject) => {
        if(this.status === FULFILLED){
            let result = successCallback(this.value);
            resolvePromise(result, resolve, reject);
        }else if(this.status === REJECTED){
            let result = failCallback(this.reason);
            resolvePromise(result, resolve, reject);
        }else if(this.status === PENDING){
            // 保存成功失败回调需要增加一层,这样就能处理回调返回值
            this.successCallbacks.push(() => {
                let result = successCallback(this.value);
                resolvePromise(result, resolve, reject);
            });
            this.failCallbacks.push(() => {
                let result = failCallback(this.reason);
                resolvePromise(result, resolve, reject);
            });
        }
    });
    return p2;
}

处理回调是个 promise

function resolvePromise(x, resolve, reject){
    if(x instanceof MyPromise){
        x.then(resolve, reject);
    }else{
        resolve(x);
    }
}

捕获异常

  1. 增加一个 catch 方法
  2. 处理立即执行中的异常和 then 方法回调中的异常(这两都比较容易,直接在原来操作外使用try catch) 处理立即执行中的异常
constructor(executor){
    try{
        executor(this.resolve, this.reject);
    }catch(e){
        this.reject(e);
    }
}

处理 then 方法回调中的异常

then(successCallback, failCallback){
    // 参数可选
    successCallback = successCallback ? successCallback : value => value;
    // 参数可选
    failCallback = failCallback ? failCallback: reason => { throw reason };
    let p2 = new MyPromise((resolve, reject) => {
        if(this.status === FULFILLED){
            try{
                let result = successCallback(this.value);
                resolvePromise(result, resolve, reject);
            }catch(e){
                reject(e);
            }
        }else if(this.status === REJECTED){
            try{
                let result = failCallback(this.reason);
                resolvePromise(result, resolve, reject);
            }catch (e) {
                reject(e);
            }
        }else if(this.status === PENDING){
            this.successCallbacks.push(() => {
                try{
                    let result = successCallback(this.value);
                    resolvePromise(result, resolve, reject);
                }catch (e) {
                    reject(e);
                }
            });
            this.failCallbacks.push(() => {
                try{
                    let result = failCallback(this.reason);
                    resolvePromise(result, resolve, reject);
                }catch (e) {
                    reject(e);
                }
            });
        }
    });
    return p2;
}

创建 catch 方法(直接调用then方法)

catch(failCallback){
    return this.then(undefined, failCallback)
}

添加 Promise.resolve

  1. 处理 promise 实例,直接返回
  2. 处理 thenAbled对象(具有then方法的对象)
  3. 处理其它
static resolve(value){
    if(value instanceof MyPromise){
        return value;
    }else if(Object.prototype.toString.call(value) === '[object Object]'
        && Object.prototype.toString.call(value.then) === '[object Function]'){
        return new MyPromise(value.then);
    } else {
        return new MyPromise(resolve => resolve(value));
    }
}

添加 finally 方法

  1. 在成功和失败后都执行
  2. 处理 finally 回调返回 promise
finally(callback){
    const P = this.constructor;
    // callback中如果返回的promise是rejected,返回的promise是rejected
    // 如果返回的promise是fulfilled,返回的promise保持原来的
    return this.then(
        res => P.resolve(callback()).then(() => res, err => err),
        err => P.resolve(callback()).then(() => {throw err}, err => err)
    )
}

实现 all 方法

static all(arr){
    return new MyPromise((resolve, reject) => {
        let result = [];

        function addResult(key, value){
            result[key] = value;
            if(result.length === arr.length){
                resolve(result);
            }
        }

        arr.forEach((value, index) => {
            if(value instanceof MyPromise){
                value.then(res => {
                    addResult(index, res);
                }, err => {
                    reject(err);
                })
            }else{
                addResult(index, value);
            }
        })
    })
}

完整代码

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

class MyPromise{
    constructor(executor){
        try{
            executor(this.resolve, this.reject);
        }catch(e){
            this.reject(e);
        }
    }

    status = PENDING;
    value = '';
    reason = '';
    successCallbacks = [];
    failCallbacks = [];


    resolve = value => {
        if(value instanceof MyPromise){
            value.then(this.resolve, this.reject);
            return;
        }
        if(this.status !== PENDING) return;
        this.status = FULFILLED;
        this.value = value;
        while (this.successCallbacks.length){
            this.successCallbacks.shift()();
        }
    }

    reject = reason => {
        if(this.status !== PENDING) return;
        this.status = REJECTED;
        this.reason = reason;
        while (this.failCallbacks.length){
            this.failCallbacks.shift()();
        }
    }

    then(successCallback, failCallback){
        // 参数可选
        successCallback = successCallback ? successCallback : value => value;
        // 参数可选
        failCallback = failCallback ? failCallback: reason => { throw reason };
        let p2 = new MyPromise((resolve, reject) => {
            if(this.status === FULFILLED){
                try{
                    let result = successCallback(this.value);
                    resolvePromise(result, resolve, reject);
                }catch(e){
                    reject(e);
                }
            }else if(this.status === REJECTED){
                try{
                    let result = failCallback(this.reason);
                    resolvePromise(result, resolve, reject);
                }catch (e) {
                    reject(e);
                }
            }else if(this.status === PENDING){
                this.successCallbacks.push(() => {
                    try{
                        let result = successCallback(this.value);
                        resolvePromise(result, resolve, reject);
                    }catch (e) {
                        reject(e);
                    }
                });
                this.failCallbacks.push(() => {
                    try{
                        let result = failCallback(this.reason);
                        resolvePromise(result, resolve, reject);
                    }catch (e) {
                        reject(e);
                    }
                });
            }
        });
        return p2;
    }

    catch(failCallback){
        return this.then(undefined, failCallback)
    }

    finally(callback){
        const P = this.constructor;
        // callback中如果返回的promise是rejected,返回的promise是rejected
        // 如果返回的promise是fulfilled,返回的promise保持原来的
        return this.then(
            res => P.resolve(callback()).then(() => res, err => err),
            err => P.resolve(callback()).then(() => {throw err}, err => err)
        )
    }

    static resolve(value){
        if(value instanceof MyPromise){
            return value;
        }else if(Object.prototype.toString.call(value) === '[object Object]'
            && Object.prototype.toString.call(value.then) === '[object Function]'){
            return new MyPromise(value.then);
        } else {
            return new MyPromise(resolve => resolve(value));
        }
    }

    static all(arr){
        return new MyPromise((resolve, reject) => {
            let result = [];
    
            function addResult(key, value){
                result[key] = value;
                if(result.length === arr.length){
                    resolve(result);
                }
            }
    
            arr.forEach((value, index) => {
                if(value instanceof MyPromise){
                    value.then(res => {
                        addResult(index, res);
                    }, err => {
                        reject(err);
                    })
                }else{
                    addResult(index, value);
                }
            })
        })
    }
}

function resolvePromise(x, resolve, reject){
    if(x instanceof MyPromise){
        x.then(resolve, reject);
    }else{
        resolve(x);
    }
}

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgajkfe
系列文章
更多 icon
同类精品
更多 icon
继续加载