手写promise没你想象中那么难(下)

121 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

大家好,我是除了开发,什么都想试试的布布。目前Promise 是 JavaScript 异步编程的一种流行解决方案,那理解promise原理早该提上日程了。理解原理?除了原生手写promise库,还能有什么更好的解决办法吗?

实现promise周边方法

上一期已经实现了状态以及then的相关问题,手写promise其实也已经接近尾声了,这一期主要实现周边方法。(本期代码是在上一期代码的基础上,进行的补充,所以请至上期文章最后copy全代码)

手写promise没你想象中那么难(上)

周边方法主要分为两大类:

  1. 原型方法 catch 、finally
  2. 静态方法 race all allSettled resolve reject

catch

注册 catch 方法来处理错误,在then之后调用,与try/catch语句有相同的功能。then会返回一个promise对象,所以catch也是promise对象中的一个方法。catch中传入的是一个函数。

    catch(fn) {
        return this.then(undefined, fn);
    }

resolve reject

都返回一个新的promise对象。

    static resolve(val) {
        return new MPromise(resolve => {
            resolve(val);
        })
    }
    static reject(err) {
        return new MPromise((resolve, reject) => {
            reject(err);
        })
    }

finally

注意执行顺序,无论成功还是失败都要执行,需要注册到执行队列里面。

  finally(cb){
        this.then(cb,cb);
    }

race

接收数组,执行之后调用then 方法,则说明race返回的是一个promise对象,成功或失败都是抛出数组中执行最快的那个结果(注意:如果已经抛出成功或失败需要控制就不再抛出)。

    static race(lists) {
        let isExe = false;
        return new KPromise((resolve, reject) => {
            lists.forEach(item => {
                item.then(res => {
                    if (!isExe) {
                        resolve(res);
                        isExe = true;
                    }
                }, err => {
                    if (!isExe) {
                        reject(err);
                        isExe = true;
                    }

                })
            })
        })
    }

all

将所有结果收集起来进行返回,但注意只返回成功的结果集,失败的收集不到

    static all(lists){
        let resArr = [];
        let num = 0;
        return new MPromise(resolve=>{
            lists.forEach(item=>{
                item.then(res=>{
                    num++;
                    resArr.push(res);
                    if(resArr.length===lists.length){
                        resolve(resArr);
                    }
                })
            })
        })
    }

allSettled

把成功和失败的返回结果收集起来之后,返回到成功的resolve里,找合适的位置进行抛出。

    static allSettled(lists){
        let resArr = new Array(lists.length);
        let num = 0
        return new KPromise(resolve=>{
            lists.forEach((item,key)=>{
                let obj = {};
                item.then(res=>{
                     obj['status'] = "fulfilled";
                     obj['value'] = res;
                     resArr[key] = obj;
                     num++;
                     if(num>=lists.length){
                        resolve(resArr);
                     }
                },err=>{
                    obj['status'] = "rejected";
                    obj['reason'] = err;
                    resArr[key] = obj;
                    num++;
                    if(num>=lists.length){
                        resolve(resArr);
                     }
                })
            })
        })
    }

好了,promise周边方法已经写得差不多了,下面写点面试题练练吧!

     var promise = new Promise(function (resolve, reject) {
         setTimeout(function () {
            resolve(1);
         }, 1000)
     })


    // 1 
    promise.then(() => {
       return Promise.resolve(2);
    }).then((n) => {
       console.log(n)
    });

    // 2
    promise.then(() => {
       return 2
    }).then((n) => {
       console.log(n)
    });

    // 3
    promise.then(2).then((n) => {
       console.log(n)
    });

评论区写下你的答案吧!