在第一章,我们认识到了事件的概念以及处理事件最重要两个对象:事件循环机制,并发事件。只在这一章,我们对事件进行进一步分割。在上一张,我们提到js所有事件分为两种:现在的事件和将来的事件。在这里,我们进一步分割:将一个事件分为’现在‘与’将来‘。也就是异步事件。
回调曾经是异步的主力军。但是在技术发展的河流中,他也被冲刷出嶙峋的创口。在遥远的前端平原上,一颗新星正冉冉升起。没错,他就是我们的promise。所谓promise者,承诺也,希望也。
回调是如何衰落的?promise又是如何接过火炬,在狼环虎伺的市场上杀出自己的生态链,挤死那些不支持promise编程的友商的?在这一章我们将一一道来。
2.1 continuation:回调函数的致命伤,时间尺度分割代码,抽象的来源之一
随着网络请求,io流等中间有停顿或需要反馈才能继续的事件的出现,函数不得不将自己分成两部分。这就是回调函数。回调函数包裹了程序的延续,也就是所谓的continuation
但是不得不说,这种鸡贼的方法确实使得函数有了先后之说,但是也让代码变得更加抽象,难以追踪,调试,和维护。
这里就出现了回调的第一个bug:和人脑的逻辑严重不符。我不禁想起高中语文中学过的插叙:为了达到文学的目的,强行一波回忆杀。光是一次回溯就让读者有点难受了,试想一下,博客写道现在都依照者ABCDE的顺序在讲解,如果我写的顺序是这样的:ABCADEBCED,什么感受,简直是折磨吧。
实际上,我们的大脑的工作方式有点类似于事件循环队列,但是只能映射同步代码语句。插入宏事件,微事件后,大脑就有点开始打架了。
这胡导致一个很崩溃的事实:这段回调代码确实是我写的,但是我对他的开发不足百分之一。有些时候我们认为他人(的代码)即地狱,这个时候我们会遇到一个更加沮丧的事实:最大的敌人是自己(的代码)。
2.2嵌套函数与链式回调:回调地狱的致命伤在哪里
我一直觉得这个名字很搞笑:回调地狱,毁灭金字塔。第一次在书中看到这两个词,就好像看见课堂上精神矍铄的老教师突然大喊妮可妮可妮。
提到回调地狱大家肯定都不陌生,在书中就举了这样一个简单的例子:
答案揭晓,运行结果是AFBCED。稍微有点头痛吧。那我现在再将其中一个或几个函数换位异步函数呢?结果不仅复杂,还要分情况了 。
真实的js代码比这个混乱的多,异步加回调使得追踪的难度成倍增加,并且可想而知你的代码本身就会变得脆弱。我当然也可以做无数的预设,将所有可能性都写出来。这样一来结果似乎变得好一些了:从脆弱但相对简单的一列代码变成了不知道脆不脆弱但是肯定七手八脚,麻烦无比的一堆代码。
这才是回调地狱的真正原因,嵌套和缩进只是转移注意力的枝节而已。
2.3 信任问题:真的能相信别人的代码吗?
回调里面有一个很微妙的驱动设计问题:控制反转
它以这样一个思路为中心:有时候 ajax(..)(也就是你交付回调 continuation 的第三方)不是你编写的代码,也不在你的直接控制下。多数情况下,它是某个第三方提供的工具。
你能完全信任对面真的会按照你的希望去调用你的代码吗?就比如你是一个支付网站,他是第三方,你和他的支付逻辑共存于一套回调系统中。当用户需要付钱,输入密码后,它收到消息开始调用你的函数收钱。它真的会乖乖调用吗?万一它调用不止一次呢?用户买了一次然后发现钱被扣了十次,这就是事故了。或者它干脆不调用呢,你的支付请求就要一直卡在这里吗?
调用回调过早(在追踪之前);• 调用回调过晚(或没有调用);• 调用回调的次数太少或太多(就像你遇到过的问题!);• 没有把所需的环境 / 参数成功传给你的回调函数;• 吞掉可能出现的错误或异常;
这些都是可能的问题。你逐渐意识到,对于被传给你的无法信任的工具的每个回调,你都不得不创建大量混乱的逻辑。
在此基础上,我们来再进一步。看看你的代码里面引用的第三方库,你真的能信任那些库吗?那些插件,那些你没有看过原码的工具,你真的敢将他插入你的回调函数中,将代码的执行大权移交给对方吗?
所以,对于回调,我们至少要在内部函数构建一些防御性的参数检查。但是回调函数本身并没有任何机制支持这一点,我们不得不自己完成这块代码的全部逻辑。
那么现在你的代码已经有了bug,即使他们还未对你造成伤害,但是,隐藏的bug那也是bug。
2.4 小结
从上面的代码我们可以直接看见:回调已经不够用了,第一:他和我们的大脑运作方式不符合。第二,他会带来信任危机。第三,回调地狱的问题也需要解决。我们迫切需要一种比回调更好的机制,给js异步处理带来新的生机。
回调:打开异步的大门&spm=1001.2101.3001.5002&articleId=142371218&d=1&t=3&u=1569b7f15fe5498e80dacb121853862c)
2577

被折叠的 条评论
为什么被折叠?



