Last active
November 20, 2015 03:30
-
-
Save stableShip/eeae7809d653452c0139 to your computer and use it in GitHub Desktop.
js异步流程控制
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#js异步流程控制 | |
##为什么会有异步流程控制 | |
###1.使用callback | |
错误处理:传统的try/catch形式无法捕获到callback中的错误 | |
回调地狱:使用callback会造成回调地狱. | |
``` | |
doAsync1(function () { | |
doAsync2(function () { | |
doAsync3(function () { | |
doAsync4(function () { | |
... | |
}) | |
}) | |
}) | |
``` | |
###2.使用事件监听: | |
另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。 | |
还是以f1和f2为例。首先,为f1绑定一个事件。 | |
`f1.on('done', f2);` | |
上面这行代码的意思是,当f1发生done事件,就执行f2 | |
这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰,无法调试. | |
###3.发布/订阅 | |
上一节的"事件",完全可以理解成"信号"。 | |
我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern),又称"观察者模式"(observer pattern)。 | |
首先,f2向"信号中心"jQuery订阅"done"信号。 | |
`jQuery.subscribe("done", f2);` | |
向"信号中心"jQuery发布"done"信号,就会执行f2函数 | |
`jQuery.publish("done");` | |
f2完成执行后,也可以取消订阅(unsubscribe)。 | |
`jQuery.unsubscribe("done", f2);` | |
这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。 | |
##异步流程控制 | |
###promise: | |
Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。 | |
简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成: | |
`f1().then(f2);` | |
这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现许多强大的功能。 | |
比如,指定多个回调函数: | |
` f1().then(f2).then(f3);` | |
如果一个任务已经完成,回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。 | |
Promise 的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。 | |
###thunk: | |
一种将会掉函数返回的形式 | |
``` | |
function readFile(fileName){ | |
return function (callback){ | |
return fs.readFile(fileName, callback); | |
}; | |
}; | |
var readFileThunk = readFile(fileName); | |
readFileThunk(callback); | |
``` | |
fs 模块的 readFile 方法是一个多参数函数,两个参数分别为文件名和回调函数。经过转换器处理,它变成了一个单参数函数,只接受回调函数作为参数。这个单参数版本,就叫做 Thunk 函数。 | |
Thunk 函数有什么用?回答是以前确实没什么用,但是 ES6 有了 Generator 函数,Thunk 函数现在可以用于 Generator 函数的自动流程管理。 | |
var gen= function* (){ | |
var r1 = yield readFile('test.json'); | |
console.log(r1.toString()); | |
var r2 = yield readFile('test1.json'); | |
console.log(r2.toString()); | |
}; | |
var g = gen(); | |
g.next() //test.json | |
g.next() // test1.json | |
yield 返回了{value: someValue ,done: boolean } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment