链式调用的实现,实现了Promise的多步骤流程控制功能,对一个多于两个步骤的流程中,即使没有实现链式调用,Promise实际上依然可以工作,但当你真的那样做时,你会发现它又变成了一个新的回调地狱。
Promise的可靠性是指什么?
Promise的可靠性指它的状态只能被改变一次,之后就不能再修改,且唯一修改它的方法是调用promise实例中的内部resolve( )或reject( )方法,它们是定义在Promise内部的,从外部无法访问到,只能通过Promise内部提供的机制来触发判定方法(new Promise(executor)生成实例时,当还行到executor时,Promise会将内部的resolve和reject方法作为实参传入executor,从而暴露修改自身状态的能力),相比之下,普通对象的属性或者thenable对象(指拥有then方法的非Promise实例对象)的属性都是可以被直接修改的,所以promise的状态和结果被认为是更可靠的。
三. 写给小白的Promise短篇故事假设有一个异步的动作A,还有一个希望在A完成以后执行的动作B,和一个在B完成以后去执行的动作C,我们来看一下Promise是如何实现流程控制。
第一回 状态标记A动作开始之前,我们把它丢进Promise构造函数,Promise给了A一个控制器(上面有resolve和reject两个按钮)和一个带有两个抽屉的储物柜(onFulfilledCallbacks和onRejectedCallbacks),接着给A交代:我已经登记好信息了,你去执行吧,等你执行完以后,如果你认为执行成功了,就按一下控制器的resolve按钮,如果认为执行失败了就按一下reject按钮,但是你要小心,这个控制器只能用一次,按完它会自动发送消息,储物柜上有接收器,如果收到resolve信号,onFulfilledCallbacks这个抽屉就会打开,如果收到reject信号,onRejectedCallbacks这个抽屉就会打开,之后另一个柜子就会锁死,我每隔一段时间会来查看一下你的状态(注意这里是在事件循环中主动轮询来查看promise实例是否执行结束的),如果我看到你的储物柜有一个抽屉打开了的话的话,就会把里面的东西拿出来依次执行接下来的事情。在这之前,如果有人想关注你的执行情况的话,我会让它留下两张字条,分别写下不同的抽屉打开的时需要做的事情,因为最终只有一个抽屉可以打开,他必须得写两张字条,除非他只关注某个抽屉的动向,然后使用你这个储物柜的then方法就可以把字条塞到对应的柜子里,之后等抽屉打开时,我只需要根据字条上的信息打电话给他就行了。A觉得这样是比较稳妥的,于是拿着promise给它的控制器去执行了。
第二回 回调注册代码继续执行,这时候出现了一个B,B说我得先看看A的执行结果,再决定做什么,执行器说你也别在这干等着了,A在我们这里存放了一个智能储物柜,它回头会把结果远程发送回来,你把你的联系方式写在这两张字条上,然后通过A的储物柜的then方法放进去吧,联系方式也可以写成不一样的,到时候A返回结果的话,对应的抽屉就会打开,我按照你写的联系方式发消息给你就行了。B想了想也是,于是就写下了两个不同的号码放进了A储物柜对应的抽屉里,接着就回家睡觉去了。
第三回 机制缺陷代码继续执行,这时候又出现了一个C,C说我想等B返回结果以后再执行,这时候执行器犯难了,B还没出发呢,我也没有给它分配回调储物柜,所以没办法用同样的方式对待C,执行器只能对C说,我们这规定如果没有对应标记的储物柜的话,暂时不提供服务,这样吧,你先把你的联系方式写好交给我,等回头如果B出发的话,我会给它分派储物柜,到时候把你的需求放在对应的抽屉里,等B返回对应结果以后我再通知你,C觉得也行,于是就照做了。但是C走后,执行器就想了,要是后面再来DEF都要跟在不同的人后面去执行,那这些事情我都得先保管着,这也太累了,而且容易搞乱,不能这么搞啊。
第四回 流程管理上一会讲到在现有机制下缺乏多步骤流程管理的机制,当异步任务A执行且没有返回结果时,后续所有的动作都被暂存在了执行器手里,只能随着时间推移,当标志性事件发生时再逐步去分发事件。为了能够实现多步骤的流程管理,执行器想出了一个方法,为每一个来注册后续业务逻辑的人都提供一个智能储物柜,这样在办理登记时就可以直接将后续的方法分发到对应的抽屉里,常见的问题就解决了。
四.链式调用Promise的影响