异步迭代生成器

function foo(x,y,cb) {
         ajax(
             "http://some.url.1/?x=" + x + "&y=" + y,
cb );
}
     foo( 11, 31, function(err,text) {
         if (err) {
             console.error( err );
         }
         else {
             console.log( text );
} } );


如果想要通过生成器来表达同样的任务流程控制,可以这样实现:
 

   function foo(x,y) {
         ajax(
             "http://some.url.1/?x=" + x + "&y=" + y,
             function(err,data){
if (err) {
// 向*main()抛出一个错误 it.throw( err );
}
else {
// 用收到的data恢复*main()
                     it.next( data );
                 }
} );
}
     function *main() {
         try {
             var text = yield foo( 11, 31 );
             console.log( text );
         }
         catch (err) {
             console.error( err );
} }
     var it = main();


// 这里启动! it.next();
第一眼看上去,与之前的回调代码对比起来,这段代码更长一些,可能也更复杂一些。 但是,不要被表面现象欺骗了!生成器代码实际上要好得多!不过要解释这一点还是比 较复杂的。
首先,让我们查看一下最重要的这段代码:
     var text = yield foo( 11, 31 );
     console.log( text );
请先花点时间思考一下这段代码是如何工作的。我们调用了一个普通函数 foo(..),而且 显然能够从 Ajax 调用中得到 text,即使它是异步的。
这怎么可能呢?如果你回想一下第 1 章的开始部分的话,我们给出了几乎相同的代码: var data = ajax( "..url 1.." );
console.log( data ); 但是,这段代码不能工作!你能指出其中的区别吗?区别就在于生成器中使用的 yield。
这就是奥秘所在!正是这一点使得我们看似阻塞同步的代码,实际上并不会阻塞整个程 序,它只是暂停或阻塞了生成器本身的代码。
在yield foo(11,31)中,首先调用foo(11,31),它没有返回值(即返回undefined),所以 我们发出了一个调用来请求数据,但实际上之后做的是yield undefined。这没问题,因 为这段代码当前并不依赖 yield 出来的值来做任何事情。本章后面会再次讨论这一点。
这里并不是在消息传递的意义上使用 yield,而只是将其用于流程控制实现暂停 / 阻塞。实 际上,它还是会有消息传递,但只是生成器恢复运行之后的单向消息传递。
所以,生成器在 yield 处暂停,本质上是在提出一个问题:“我应该返回什么值来赋给变量 text ?”谁来回答这个问题呢?
看一下 foo(..)。如果这个 Ajax 请求成功,我们调用: it.next( data );
这会用响应数据恢复生成器,意味着我们暂停的 yield 表达式直接接收到了这个值。然后 随着生成器代码继续运行,这个值被赋给局部变量 text。
很酷吧? 回头往前看一步,思考一下这意味着什么。我们在生成器内部有了看似完全同步的代码
(除了 yield 关键字本身),但隐藏在背后的是,在 foo(..) 内的运行可以完全异步。 这是巨大的改进!对于我们前面陈述的回调无法以顺序同步的、符合我们大脑思考模式的
 方式表达异步这个问题,这是一个近乎完美的解决方案。
从本质上而言,我们把异步作为实现细节抽象了出去,使得我们可以以同步顺序的形式追 踪流程控制:“发出一个 Ajax 请求,等它完成之后打印出响应结果。”并且,当然,我们 只在这个流程控制中表达了两个步骤,而这种表达能力是可以无限扩展的,以便我们无论 需要多少步骤都可以表达。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值