资讯专栏INFORMATION COLUMN

Promise链式调用解析

roadtogeek / 1909人阅读

摘要:链式调用解析关于是做什么的我就不赘述了,当你看到这个文章的时候,我也就默认你是用过的首先,举个例子获取用户通过用户获取该用户的手机号两个方法,简称和简称两者都是了一个实例,前者是获取用户,后者是拿着用户去换取手机号,的输出是依赖于的输出,这

Promise链式调用解析

关于Promise是做什么的我就不赘述了,当你看到这个文章的时候,我也就默认你是用过Promise的

首先,举个例子

// 获取用户id
function getUserId() {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        resolve(186)
      }, 1e3)
    })
}
// 通过用户id获取该用户的手机号
function getMobileByUserId(userId) {
    return new Promise(function(resolve, reject) {
        setTimeout(function(){
            resolve(userId + "****5836")
        }, 1e3)
    })
}

两个方法,getUserId(简称 IDfun )和getMobileByUserId(简称 MOfun ),两者都是return了一个Promise实例,前者是获取用户id,后者是拿着用户id去换取手机号,MOfun的输出是依赖于IDfun的输出,这样两个异步的操作又得保证其是有序的执行

到这,应该都有一个对应的解决办法,我这里列举了一个示例:

IDfun()
    .then(MOfun)
    .then(function(res) {
        console.log(res)
    })

首先,调用了IDfun,在其Promise实例的then方法中传入MOfun,紧随其后又是一个then方法,里面传入了一个callback函数,此时,callback函数中打印的值是什么,又是为什么呢,一般情况下then方法里传的都是一个callback,而这个例子里传的却是一个包含Promise的函数,它内部是怎么做到将用户的id传递给MOfun中并打印出来

说到这,我先列举几个Promise中几个比较核心的方法:

// this指向是Promise实例
// 只列举了几个关键的代码
this.then = function (onFulfilled) {
    return new Promise(function (resolve) {
        handle({
            onFulfilled: onFulfilled || null,
            resolve: resolve
        });
    });
};

function handle(deferred) {
    if (state === "pending") {
        deferreds.push(deferred);
        return;
    }

    var ret = deferred.onFulfilled(value);
    deferred.resolve(ret);
}
// 其中的state和value可以理解为全局定义的,只是放了一些代码段出来
function resolve(newValue) {
    if (newValue && (typeof newValue === "object" || typeof newValue === "function")) {
        var then = newValue.then;
        if (typeof then === "function") {
            then.call(newValue, resolve);
            return;
        }
    }
    state = "fulfilled";
    value = newValue;     // value这里可以理解为它是在全局定义的
    setTimeout(function () {
        deferreds.forEach(function (deferred) {
            handle(deferred);
        });
    }, 0);
}

参照这几个方法,我们再回到刚才那个例子:

1.执行IDfun返回一个Promise实例( IDPro ),执行IDPro中的代码,假设此时在异步发送请求,继续执行then方法,then方法中传入了MOfun

2.进入到then方法中,也是返回一个Promise实例( BridgePro1 ),调用handle方法

handle({

onFulfilled: onFulfilled || null,  // 此时的onFulfilled === MOfun
resolve: resolve  // resolve是BridgePro1的resolve

});

3.进入handle中,如果是IDPro的then方法先执行,其resolve后执行,这个时候 state === pending,此时它会将传入的对象push到IDPro的deferreds数组中,然后返回

4.IDPro中异步操作完成,执行其resolve,并传入id为186

5.进入resolve方法中,此时newValue不满足if条件,跳过,继续向下执行,改变state===> fulfilled,value ===> 186,setTimeout为0是为了把其内部的这段代码放到队列的最后,保证执行这段代码的时候then方法已经执行了,循环遍历IDPro的deferreds数组,将数组中的每一项传入handle中并执行

function resolve(newValue) {   // newValue === 186
        if (newValue && (typeof newValue === "object" || typeof newValue === "function")) {
            var then = newValue.then;
            if (typeof then === "function") {
                then.call(newValue, resolve);
                return;
            }
        }
        state = "fulfilled";
        value = newValue;     // value这里可以理解为它是在全局定义的
        setTimeout(function () {
            // deferreds里存放的是通过then传入的
            // [{
            //    onFulfilled: MOfun,
            //    resolve: resolve
            // }]
            deferreds.forEach(function (deferred) {  
                handle(deferred);
            });
        }, 0);
    }

6.进入handle中,此时state === fulfilled,执行deferred中的onFulfilled(MOfun),传入value,返回一个Promise实例(MOPro),此时的ret === MOPro,继续执行deferred中的resolve(BridgePro1的resolve),传入ret

  // state === fulfilled
    // deferred ===> 
    //  {
    //    onFulfilled: MOfun,
    //    resolve: resolve
    //  }
    function handle(deferred) {
        if (state === "pending") {
            deferreds.push(deferred);
            return;
        }
    
        var ret = deferred.onFulfilled(value);  // value === 186
        deferred.resolve(ret);
    }

7.进入resolve中,此时newValue满足判断条件

    function resolve(newValue) {   // newValue === MOPro
        if (newValue && (typeof newValue === "object" || typeof newValue === "function")) {
            // then 是MOPro的then
            var then = newValue.then;
            if (typeof then === "function") {
                // 调用then方法,设置其内部this指向为MOPro,并传入resolve,这个resolve为BridgePro1的resolve,然后返回
                then.call(newValue, resolve);
                return;
            }
        }
        state = "fulfilled";
        value = newValue;     
        setTimeout(function () {
            deferreds.forEach(function (deferred) {  
                handle(deferred);
            });
        }, 0);
    }

8.进入到MOPro的then方法中,调用handle将对象传入,此时MOPro的deferreds数组中有两项,一项是上面通过resolve传入的,另一项是传入的callback函数

// ===> callback
    function(res) {
        console.log(res)
    }

    this.then = function (onFulfilled) {
        // onFulfilled为BridgePro1的resolve 
        // 此时返回的Promise实例为BridgePro2
        return new Promise(function (resolve) {
            handle({
                onFulfilled: onFulfilled || null,
                resolve: resolve  // BridgePro2
            });
        });
    };

9.当MOPro中异步操作执行完成,执行resolve并传入手机号1865836,进入resolve,将state设置为fulfilled,value设置成1865836,延迟循环MOPro的deferreds数组,此时数组为:

[
        {
            onFulfilled: resolve,   // BridgePro1的resolve
            resolve: resolve  // BridgePro2的resolve
        },
        {
             onFulfilled: callback,
            resolve: resolve  // BridgePro3的resolve
        }
    ]

10.进入handle方法中,循环第一个值时,此时deferred的onFulfilled为BridgePro1的resolve,调用该resolve,并传入value(1865836),因为BridgePro1的deferreds为空,所以直接resolve掉BridgePro1,此时ret为undefined,再执行deferred的resolve(BridgePro2的resolve),同样,resolve掉BridgePro2,继续循环,传入第二个值,deferred的onFulfilled为callback,执行callback传入value,打印出手机号1865836,返回值为undefined ,因此ret为undefined,再执行deferred的resolve(BridgePro3的resolve),直接resolve掉BridgePro3

 function handle(deferred) {
        if (state === "pending") {
            deferreds.push(deferred);
            return;
        }
    
        var ret = deferred.onFulfilled(value);
        deferred.resolve(ret);
    }

11.至此,执行完成,通过user的id换取了user的mobile number

后记:

如果我想按照下面的写法一直then下去:

IDfun()
    .then(MOfun)
    .then(callback)
    .then(callback)
    .then(callback)

每个callback里都可以打印到手机号,应该怎么写

// callback
function callback(res) {
    // doing something
    console.log(res)
    return res
}
总结:

Promise是什么,从字面意思就是一个承诺,我给你了一个承诺,你记着呢,不知道什么时候兑现,但肯定会给你一个答复,打一个不太形象的比喻,我去银行办事,肯定是先取一个号,这个号就像一个承诺,什么时候叫到你,不确定,但肯定会叫你,然后这个时候你就会去办理你的事情,综上,即为Promise链式的原理解析,出错的地方欢迎指出

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99236.html

相关文章

  • promise学习(1)

    摘要:原文地址定义是针对异步编程的一种解决方案,能够抽象处理异步对象以及对其进行操作。当状态由时执行已完成的回调函数,由时,调用失败的回调函数。所以,可以在自行使用,保证执行不会出错,或者使用其他异步编程方式。异步编程的方案后续学习再补充 原文地址 定义 Promise是针对异步编程的一种解决方案,能够抽象处理异步对象以及对其进行操作。Promise并不是Javascript语言的扩展,只是...

    pingink 评论0 收藏0
  • AngularJS中$q的promise使用及链式调用传值问题

    摘要:规范中文是提供的一个服务。实际调用这个方法最终在此处加入到队列中定义此处调用进入此处是链式调用传参关键,实际是上一个的的返回值,所以能知道,如果需要所有的都能取到异步任务的返回值,就得在的函数中,将值返回。 promise是什么 这里不解释promise是什么,因为我相信你来看文章的时候已经知道你什么是promise了。此处有promise规范。 Promise/A+规范 中文Prom...

    hiyayiji 评论0 收藏0
  • JavaScript 工作原理之四-事件循环及异步编程的出现和 5 种更好的 async/await

    摘要:函数会在之后的某个时刻触发事件定时器。事件循环中的这样一次遍历被称为一个。执行完毕并出栈。当定时器过期,宿主环境会把回调函数添加至事件循环队列中,然后,在未来的某个取出并执行该事件。 原文请查阅这里,略有改动。 本系列持续更新中,Github 地址请查阅这里。 这是 JavaScript 工作原理的第四章。 现在,我们将会通过回顾单线程环境下编程的弊端及如何克服这些困难以创建令人惊叹...

    maochunguang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<