顺序的大脑
我们真的可以一心多用吗?我们真的能同时执行两个有意识的,故意的动作,并对二者进行思考吗或推理吗?我们最高级的大脑功是以并行多线程的形式的形式运行的吗?
我们其实只是在快速的进行上下文切换而已,换句话说,我们是在两个或更多任务之间快速连续地来回切换,同时处理每个任务的微小片段。我们切换得如此之快,以至于对外界来说,我们就像在并行执行任务。
人体才是最牛逼的程序,心跳呼吸,眨眼,我们的大脑在后台(多线程)执行了所有这些重要任务。
执行的层级,我们的大脑是以异步事件方式运作的,但我们的任务计划似乎还是以顺序,同步的方式进行:“我要先去商店,然后再买点牛奶,然后去一下干洗店”
我们的大脑,记住不是多任务,而是快速的上下文切换
对于我们我们程序员,编写异步事件代码,特别是当回调是唯一的实现手段时,困难之处就在于思考/计划的意识流对我们中的绝大多数来说是不自然的。
嵌套回调于链式回调
原来这些写法都是有名词的,我一直在写 code,并不知道这些名词,=-= 以后面试就可以造飞机呢,我要多看看书,很多都是只会做,理解是最重要的。
listen("click",function handle(evt){
setTimeout(function request(){
ajax("http://some.url.1",function response(text){
if(text == "hello"){
handle()
}else if(text == "world"){
request()
}
})
},500);
})
一开始我们在等待 click 事件,然后等待定时器启动,然后等待 ajax 响应返回,之后可能再重头开始。
一眼看去,这段代码似乎很自然地将其异步性映射到了顺序大脑计划。
首先(现在)我们有:
listen(“click”,function handle()){
}
然后是将来,我们有:
setTimeout(function request(…){
},500)
接着还是将来,我们有:
ajax(“…”,function response(…){
})
最后
if(){
}else …
1,2,3,4…的顺序,这只是一个偶然,实际的异步 js 程序总是有很多噪声呢,事使得代码更加杂乱,在大脑的演习中,我们需要熟练地绕过这些噪声,从一个函数跳到下一个函数。
listen("click",handle);
function handle(){
setTimeout(request , 500);
}
function request(){
ajax("http://some.url.1",response);
}
function response(text){
if(text == "hello"){
handler();
}else if(text == "worl"){
request();
}
}
这种组织形式的代码不像前面以嵌套/缩进的形式组织的代码那么容易识别了,但是它和回调地域一样脆弱,易受影响。
顺序追踪这段代码,我们不得不从一个函数跳到下一个,再跳到下一个,在整个代码中跳来跳去以 “查看”流程。真实 异步 js 程序代码要混乱得多,这使得这种追踪的难度会成倍增加。
回调地域
我们的顺序阻塞式的大脑计划行为无法很好地映射到面向回调的异步代码。这就是回调方式最主要的缺陷:对于它们在代码中表达异步的方式,我们的大脑需要努力才能同步得上。
控制反转
有时候请求,或者交付回调的第三方(& ajax)不是您编写的代码,也不在你的直接控制下,多少情况下,它是某第三方提供的工具。
我们把这称为控制反转,也就是把自己程序一部分的执行控制交个某个第三方。
尝试挽救回调
有些 API 设计提供了分离回调(一个用于成功通知,一个用于出错通知)
在这种设计下,API 的出错函数 failure() 常常是可选的如果没有提供的话,就是假定这个错误可以吞掉。
回调模式 “error-first” 有时候也称为 Node 风格,因为几乎所有 Node.js 都采用这种风格
function response(err,data){
if(err){
console.log(err)
}else {
console.log(data)
}
}
ajax("http://some.url.1",response)
这并没有像表面上那样解决主要的信任问题。
这并没有涉及阻止或过滤不想要的重复调用回调的问题。
现在事情更糟了,因为现在您可能同时得到成功或者失败的结果,或者都没有,并且您还是不得不编码处理所有这些问题。
另外,冗长和模式化,可复用性不高,所以你还得不厌其烦地给应用中的每个回调添加这样的代码。
随着 JavaSctipt 越来越成熟,异步编程领域的发展,回调已经不够用了。
-
第一,大脑对于事情的计划方式是线性的,阻塞的,单线程的语义,但是回调表达异步流程的方式是非线性的,非顺序的。
-
回调会受到控制反转的影响,因为回调暗中把控制权交给第三方(通常是不受你控制的第三方工具!)来调用您代码中的 continuation
我们需要比回调更好的机制。