Promise(3):手动实现Promise扩展方法

957 阅读4分钟

接着Promise(2):手动实现Promise,为Promise添加扩展方法

1、静态方法

resolve

用于包装任意对象为promise对象,返回一个新的promise,并且状态是resolved

static resolve(value) {
    if (value instanceof this) {
        return value;
    }
    return executeCallback.call(new MPromise(), 'resolve', value);
}

reject

用于包装任意对象为promise对象,返回一个新的promise,并且状态是rejected

static reject(reason) {
    if (reason instanceof this) {
        return reason;
    }
    return executeCallback.call(new MPromise(), 'reject', reason);
}

all

  • 如果全部成功则获得成功的结果组成的数组对象,如果失败,则获得失败的信息
  • 返回一个新的Promise对象
  • 即要保证全部成功,又要保证按数组里原来的顺序返回结果
static all(iterable){
    return new MPromise((resolve, reject) => {
        if (!iterable || !Array.isArray(iterable)){
            return reject(new TypeError('all param must be an array'))
        }
        const len = iterable.length;
        let result = Array(len); //保证顺序
        let called = false; //结果不可逆
        let current = 0;

        if (len == 0){
            return resolve([]);
        }
        iterable.forEach((v, i) => {
            MPromise.resolve(v).then((value)=>{
                result[i] = value;
                current++;
                if (!called && current === len) {
                    called = true;
                    resolve(result);
                }
            }, (err)=>{
                if (!called) {
                    called = true;
                    return reject(err);
                }
            });
        });
    });
}

测试例子

function fn1() {
    return new MPromise(resolve => setTimeout(() => resolve(1), 3000))
}
function fn2() {
    return new MPromise(resolve => setTimeout(() => resolve(2), 2000))
}
MPromise.all([fn1(), fn2()]).then(res => {
    console.log(res); 
}, err => {
    console.log(err);
});
//[1,2]

race

  • 如果某个promise的状态率先改变,就获得改变的结果
  • 返回一个新的Promise对象
  • 在调用过程中会使用 Promise.resolve(value) 转换成Promise对象)
static race(iterable) {
    return new MPromise((resolve, reject) => {
        if (!iterable || !Array.isArray(iterable)) {
            return reject(new TypeError('race param must be an array'))
        }
        const len = iterable.length;
        let called = false;

        if (len == 0) {
            return resolve();
        }
        iterable.forEach((v, i)=> {
            MPromise.resolve(v).then((value)=> {

                if (called) return;
                called = true;
                return resolve(value);
            }, (reason)=> {

                if (called) return;
                called = true;
                return reject(reason);
            });
        });
    });
}

stop

这里利用,then 方法中对状态的要求必须不是 Pending 状态的处理才会立即执行回调,在 promise链 中返回一个初始状态的 Promise对象,便可以中断后面回调的执行

static stop(){
    return new Promise();
}

例子

function fn1() {
    return new MPromise(resolve => setTimeout(() => resolve(1), 1000))
}
function fn2() {
    return new MPromise(resolve => setTimeout(() => resolve(2), 1000))
}
MPromise.all([fn1(), fn2()]).then(res => {
    console.log(res);
    return MPromise.stop();
}, err => {
    console.log(err);
}).wait(3000).then(function (res) {
    console.log(res);
});

deferred

Deferred 的简称,叫延迟对象,其实是 new Promise() 的语法糖 与Promise的关系

  • Deferred 拥有 Promise
  • Deferred 具备对 Promise的状态进行操作的特权方法
  • Promise 代表了一个对象,这个对象的状态会在未来改变
  • Deferred对象 表示了一个处理没有结束,在状态发生改变时,再使用Promise来处理结果

优缺点

  • 不用使用大括号将逻辑包起来,少了一层嵌套
  • 但是缺少了Promise的错误处理逻辑
 static deferred() { 
    let defer = {};
    defer.promise = new MPromise((resolve, reject)=> {
        defer.resolve = resolve;
        defer.reject = reject;
    });
    return defer;
}

例子

function fn(){
    let deferred = MPromise.deferred();
    setTimeout(() => {
        deferred.resolve('xxxxxx');
    }, 3000);
    return deferred.promise;
}

fn().then((res) => {
    console.log(res);
})

timeout

如一个异步请求,如果超时,取消息请求,提示消息或重新请求

static timeout(promise, ms){
    return this.race([promise, this.reject().wait(ms)]);
}

sequene

用于按顺序执行一系列的promise,接收的函数数组,并不是Promise对象数组,其中函数执行时就返回Promise对象,用于有互相依赖的promise任务

static sequence(tasks){
    return tasks.reduce((prev, next)=> {
        return prev.then(next).then((v)=> v);
    }, this.resolve());
}

例子

function fn1() {
    return new MPromise(resolve => {
        setTimeout(() => {
            resolve(1)
        }, 1000)
    });
}
function fn2(data) {
    return new MPromise(resolve => {
        setTimeout(() => {
            resolve(data + 5)
        }, 1000)
    });
}

MPromise.sequence([fn1, fn2]).then(res => {
    console.log(res);
    return 'xxxx';
}, err => {
    console.log(err);
})

实例方法

wait

  • 保证链式调用,必须返回新的promise
  • 并且上一步的成功和失败的消息不能丢失,继续向后传递,这里只做延迟处理
wait(ms) { 
    return this.then((value)=>{
       return new MPromise(function (resolve, reject) {
           setTimeout(() => resolve(value), ms);
       });
    }, (reason)=>{
        return new MPromise(function(resolve, reject){
            setTimeout(() => reject(reason), ms);
        });
    });
}

always

无论成功还是失败最终都会调用 always 中注册的回调

always(fn) {
    return this.then((value)=>{
        return fn(value), value;
    }, (reason) => {
        throw fn(reason), reason;
    });
}

done

  • done方法并不返回promise对象,也就是done之后不能使用 then或catch了,其主要作用就是用于将 promise链 中未捕获的异常信息抛至外层,并不会对错误信息进行处理。
  • done方法必须应用于promise链的最后
done(onResolved, onRejected) {
    this.then(onResolved, onRejected).catch((error)=> {
        setTimeout(() => {
            throw error;
        }, 0);
    });
}

参考链接

深入理解 Promise (中)

github地址

我的github地址