深入理解Promise及其链式调用原理

最近一次面试被问到Promise链式调用原理,然而自己对promise的理解还是很浅显的,只了解其使用方法和api,对其实现原理一无所知

前言

静下心来分析。因为本人js稍弱,分析过程加深我对作用域、闭包的理解。
也非常幸运,能找到这篇由浅至深分析的博客
https://mengera88.github.io/2017/05/18/Promise原理解析/
各位童鞋们可以先看博客,最后如果分析链式调用时遇到困难的时候,可以看看我这篇博客,看能不能提供新思路。我只归纳下最后链式调用原理

链式调用

代码

简单实现,并不是源码

        function Promise(fn) {
            var callbacks = [];
            var status = 'pending';
            var value = null;
            this.then = onFulfilled => {
                return new Promise(function (resolve) {
                    handle({
                        onFulfilled: onFulfilled || null, // resolve后需要执行的回调函数
                        resolve: resolve // 当前Promise(bridge) 的resolve 
                    });
                })
            }

            function handle(callback) {
                if (status === 'pending') {
                    callbacks.push(callback); // callbacks是调用then的promise作用域里的,存储then中回调函数,不会是then返回的新promise
                    // console.log(callback.onFulfilled.toString());
                    return;
                }
                if (!callback.onFulfilled) {
                    callback.resolve(value);
                    return;
                }
                var res = callback.onFulfilled(value);   
                callback.resolve(res);   // resolve为Promise(bridge) 
            }

            function resolve(res) {
                if (res && (typeof res === 'object' || typeof res === 'function')) {
                    var then = res.then;
                    if (typeof then === 'function') {
                        then.call(res, resolve);   // 注册回调函数中返回的promise(后邻),resolve为Promise(bridge) 
                        return;
                    }
                }
                status = 'fulfilled';
                value = res;
                setTimeout(() => {
                    callbacks.forEach(cb => {
                        handle(cb);
                    });
                })

            }
            fn(resolve);
        }

        function getUserId() {
            return new Promise(function (resolve) {
                setTimeout(() => {
                    resolve('111111');
                })
            })
        }

        function getUserJobById(id) {
            console.log(id);
            return new Promise(function (resolve) {
                setTimeout(() => {
                    resolve('do some');
                })
            })
        }

        getUserId()
            .then(getUserJobById)
            .then(function (job) {
                console.log(job);
            })

注意

  • 根据执行promise时的逻辑来推演
  • 开始分析的时候可以不注意resolve是哪个Promise的,重点关注callbacks的值
  • 创建Promise实例时的函数会被立即执行
  • 主要使用了设计模式中的观察者模式
  • promise里面的then函数仅仅是注册了后续需要执行的代码,真正的执行是在resolve方法里面执行的
  • 注意 bridge Promise 的作用,用于连接(储存)后邻Promise resolve后需要执行的回调函数
  • 后邻Promise既本例中的getUserJobById Promise,其callbacks保存的并不是其resolve后需要执行的回调函数,而是bridge Promise的resolve,bridge Promise的callbacks保存了getUserJobById Promise需要执行的回调,这样就形成了链式关系。通过不同resolve来访问不同Promise的作用域,遍历相应的callbacks。为什么不是getUserJobById Promise来保存其需执行的回掉而用bridge Promise来保存,下文会分析原因

时间节点分析

和上文提到博客的分析角度不同,我以resolve的时间节点进行分析
在这里插入图片描述

  1. t1时间点。上述代码执行完毕,但getUserId Promise还没有resolve。上图只说明了getUserId Promise和bridge Promise1在这个时候被创建。其实,如果有更多的then,连接其他then的bridge Promise在这个时候也都已经被创建了。重点关注此时两个Promise的callbacks,getUserId Promise的callbacks,存储了getUserJobById函数。bridge Promise1的callbacks,存储了后邻Promise即getUserJobById Promise resolve后需执行的回调函数
  2. t2时间点。getUserId Promise resolve(‘11111’)后但getUserJobById Promise还没resolve。遍历getUserId Promise的callbacks,getUserJobById执行,生成了getUserJobById Promise。其callbacks保存了bridge Promise的resolve。
  3. t3时间点。getUserJobById Promise resolve(‘do some’)。遍历getUserJobById Promise的callbacks。之后的过程同注意的最后一点。

为什么需要 bridge Promise

        getUserId()
            .then(getUserJobById)
            .then(function (job) {
                console.log(job);
            })

为了满足这种写法,then之间必须通过Promise来连接,但前邻Promise没有resolve之前是无法得到后邻Promise的,所有需要bridge Promise来进行连接

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值