前言

承诺的一些常规用法已有记载,本文深入到一个层面来分析如何实现这一承诺规则机制。Ps:本文适合已经了解承诺用法的人。如果他们不太了解它的用法,可以转到我上一篇博文。

本文中promise的源代码是按照Promise/A+规范编写的(不想看到Promise/A+规范英文版的中文翻译)

正式介绍

为了让大家更容易理解,先从一个场景开始,按照思路一步步来,相信你会更容易理解。

考虑以下获取用户id的请求处理

看到了吗?一句简单的话就能实现如下连锁反应:

添加延迟机制

细心的同学应该会发现,上面的代码可能还存在一个问题:如果在then方法注册回调之前执行了resolve函数呢?例如,promise内部的函数是一个同步函数:

改进后的代码如下:

上面代码的思路是这样的:执行resolve的时候,状态会设置为completed,然后立即执行then添加的新回调。

这里没有一个地方的状态设置为拒绝。为了让大家关注核心代码,这个问题后面会有专门的一节。

连锁承诺

那么问题又来了。如果用户仍然在then函数中注册了一个Promise,如何解决?例如,下面的示例4:

相信用过Promise的人都知道这样的场景会有很多,所以这个叫连锁承诺。

连锁承诺(Chain Promise)是指当前承诺达到履行状态后,将开始下一个承诺。那么我们如何将当前的承诺与相邻的承诺联系起来呢?这就是这里的难点。

其实也不热,用当时的方法回个承诺就行了。承诺/A+里2.2.7就是这么说的(笑脸)~

让我们来看看这个神秘的转换代码的then方法和resolve方法:

我们结合示例4的代码来分析上面的代码逻辑。为了方便阅读,我在这里贴上例4的代码:

1.在then方法中,创建并返回一个新的Promise实例,它是串行Promise的基础,支持链式调用。

2.2.handle方法是承诺的内部方法。由then方法传入的形式参数onFulfilled和创建新promise实例时传入的解析被推送到当前promise的回调队列,这是连接当前promise和相邻Promise的关键(这里,我们必须分析好句柄的角色)。

3.getuserid(简称getUserId promise)生成的promise成功地异步操作,并执行其内部方法解析。传入的参数是异步操作的结果id

4.调用handle方法处理回调队列中的回调:getUserJobById方法生成新的承诺(getUserJobById承诺)

执行由getUserId promise的then方法生成的新promise(称为桥promise)的解析方法,传入的参数是getUserJobById promise。在这种情况下,解析方法被传递到getUserJobById promise的then方法中,并直接返回。

6.当getUserJobById承诺的异步操作成功时,在其回调中执行回调:getUserId桥承诺中的resolve方法

7.最后,在getUserId桥承诺的回调中执行回调。

比较直白的,可以看下图,一图胜千言(都是根据自己的理解画出来的,如果不欢迎指正):

故障处理

当异步操作失败时,将其状态标记为拒绝,并执行已注册的失败回调:

根据以前处理已完成状态的经验,很容易支持错误处理,在注册回调和处理状态更改时只需添加新的逻辑:

在上面的代码中,增加了一个新的reject方法,异步操作失败时可以调用,提取resolve和reject共享的部分形成execute方法。

错误冒泡是上面代码支持的一个特性,非常实用。当发现句柄中没有指定异步操作失败的回调时,bridge promise(then函数返回的promise,后面同)会直接设置为拒绝状态,从而达到执行后续失败回调的效果。这有利于简化serial Promise的故障处理成本,因为一组异步操作往往对应一个实际函数,故障处理方法通常是一致的:

异常处理

细心的同学会想:执行成功回调和失败回调时代码出错怎么办?对于这种异常,可以使用try-catch来捕获错误并将桥承诺设置为拒绝状态。处理方法修改如下:

在异步操作中,如果多次执行resolve或reject将重复处理后续回调,则可以通过构建标志位来解决这个问题。

总结

当你第一次阅读promise源代码时,你不能很好地理解promise的运行机制和解析函数,但是如果你在执行promise时冷静下来,按照逻辑推理,就不难理解了。这里必须注意的是,promise中的then函数只注册稍后要执行的代码,真正的执行是在resolve方法中执行的。澄清这一层,重新分析源代码,会节省很多精力。

现在回顾Promise的实现过程,它主要使用设计模式中的观察者模式:

1.通过Promise.prototype.then和Promise.prototype.catch方法将观察者方法注册到观察到的Promise对象中,同时返回一个新的Promise对象,这样就可以在链中调用它。

2.观察器管理内部挂起、已完成和已拒绝的状态转换,主动触发状态转换,并通过构造函数中传递的解析和拒绝方法通知观察器。

引用

深刻理解承诺:http://code rlt . coding . me/2016/12/04/promise-in-deep-an-introduction-2/

Java Promises … In缺德细节:http://www . mattgreer . org/articles/Promises-In-缺德-detail/

原始链接:

https://mengera 88 . github . io/2017/05/18/Promise % E5 % 8E % 9F % E7 % 90% 86% E8 % A7 % A3 % E6 % 9E % 90/

1.《promise 进阶 | 一篇让你彻底明白Promise原理的珍藏》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《promise 进阶 | 一篇让你彻底明白Promise原理的珍藏》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/guoji/1643563.html