1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-25 03:02:21 +00:00

edit generator/coroutine

This commit is contained in:
Ruan Yifeng 2015-04-13 08:22:40 +08:00
parent 6962500314
commit 4fdbf979b5

View File

@ -696,13 +696,21 @@ var clock = function*(_) {
### Generator与协程
协程coroutine是一种程序运行的方式。传统的“子例程”subroutine采用堆栈式“后进先出”的执行方式只有当调用的子函数完全执行完毕才会结束执行父函数。协程与其不同多个函数可以并行执行但是只有一个函数处于正在运行的状态其他函数都处于暂停态suspended函数之间可以交换执行权。也就是说一个函数执行到一半可以暂停执行将执行权交给另一个函数等到稍后收回执行权的时候再恢复执行。这种可以并行执行、交换执行权的函数就称为协程。
协程coroutine是一种程序运行的方式,可以理解成“协作的线程”或“协作的函数”。协程既可以用单线程实现,也可以用多线程实现。前者是一种特殊的子例程,后者是一种特殊的线程。
不难看出协程适合用于多任务运行的环境。在这个意义上它与线程很相似都有自己的执行上下文、可以分享全局变量。它们的不同之处在于同一时间可以有多个线程处于运行状态但是运行的协程只能有一个其他都处于暂停状态。此外线程是抢先式的到底哪个线程优先得到资源必须由运行环境决定但是协程是合作式的执行权由协程自己分配。从实现上看在内存中子例程只使用一个栈stack而协程是同时存在多个栈但只有一个栈是在运行状态也就是说协程是以多占用内存为代价实现多任务的并行。
**1协程与子例程的差异**
Generator函数是ECMAScript 6对协程的实现但属于不完全实现只做到了暂停执行和转移执行权有一些特性没有实现比如不支持所调用的函数之中的yield语句即递归执行yield语句
传统的“子例程”subroutine采用堆栈式“后进先出”的执行方式只有当调用的子函数完全执行完毕才会结束执行父函数。协程与其不同多个线程单线程情况下即多个函数可以并行执行但是只有一个线程或函数处于正在运行的状态其他线程或函数都处于暂停态suspended线程或函数之间可以交换执行权。也就是说一个线程或函数执行到一半可以暂停执行将执行权交给另一个线程或函数等到稍后收回执行权的时候再恢复执行。这种可以并行执行、交换执行权的线程或函数就称为协程
如果将Generator函数看作多任务运行的方式存在多个进入点和退出点。那么一方面并发的多任务可以写成多个Generator函数另一方面继发的任务则可以按照发生顺序写在一个Generator函数之中然后用一个任务管理函数执行参考本节的“控制流管理”部分
从实现上看在内存中子例程只使用一个栈stack而协程是同时存在多个栈但只有一个栈是在运行状态也就是说协程是以多占用内存为代价实现多任务的并行。
**2协程与普通线程的差异**
不难看出,协程适合用于多任务运行的环境。在这个意义上,它与普通的线程很相似,都有自己的执行上下文、可以分享全局变量。它们的不同之处在于,同一时间可以有多个线程处于运行状态,但是运行的协程只能有一个,其他协程都处于暂停状态。此外,普通的线程是抢先式的,到底哪个线程优先得到资源,必须由运行环境决定,但是协程是合作式的,执行权由协程自己分配。
由于ECMAScript是单线程语言只能保持一个调用栈。引入协程以后每个任务可以保持自己的调用栈。这样做的最大好处就是抛出错误的时候可以找到原始的调用栈。不至于像异步操作的回调函数那样一旦出错原始的调用栈早就结束。
Generator函数是ECMAScript 6对协程的实现但属于不完全实现。Generator函数被称为“半协程”semi-coroutine意思是它还要借助yield语句将执行权给它的调用者。执行权可以发生转移的地方都要靠yield语句注明没有yield语句的地方执行权就不能转移。完全实现的协程没有yield语句任意位置都可以暂停将执行权转移出去。
## 应用