详解JavaScript ES6中的Generator(3)

function* filter(test, iterable) { for (var item of iterable) { if (test(item)) yield item; } } function* filter(test, iterable) { for (var item of iterable) { if (test(item)) yield item; } }

所以,Generator 很实用吧?当然,这是实现自定义迭代器最简单直接的方式,并且,在 ES6 中,迭代器是数据集和循环的新标准。

但,这还不是 Generator 的全部功能。
异步代码

异步 API 通常都需要一个回调函数,这意味着每次你都需要编写一个匿名函数来处理异步结果。如果同时处理三个异步事务,我们看到的是三个缩进层次的代码,而不仅仅是三行代码。

看下面代码:

}).on('close', function () { done(undefined, undefined); }).on('error', function (error) { done(error); }); }).on('close', function () { done(undefined, undefined); }).on('error', function (error) { done(error); });

异步 API 通常都有错误处理的约定,不同的 API 有不同的约定。大多数情况下,错误是默认丢弃的,甚至有些将成功也默认丢弃了。

直到现在,这些问题仍是我们处理异步编程必须付出的代价,而且我们也已经接受了异步代码只是看不来不像同步代码那样简单和友好。

Generator 给我们带来了希望,我们可以不再采用上面的方式。

Q.async()是一个将 Generator 和 Promise 结合起来处理异步代码的实验性尝试,让我们的异步代码类似于相应的同步代码。

例如:

// Synchronous code to make some noise. function makeNoise() { shake(); rattle(); roll(); } // Asynchronous code to make some noise. // Returns a Promise object that becomes resolved // when we're done making noise. function makeNoise_async() { return Q.async(function* () { yield shake_async(); yield rattle_async(); yield roll_async(); }); } // Synchronous code to make some noise. function makeNoise() { shake(); rattle(); roll(); } // Asynchronous code to make some noise. // Returns a Promise object that becomes resolved // when we're done making noise. function makeNoise_async() { return Q.async(function* () { yield shake_async(); yield rattle_async(); yield roll_async(); }); }

最大的区别在于,需要在每个异步方法调用的前面添加 yield 关键字。

在 Q.async 中,添加一个 if 语句或 try-catch 异常处理,就和在同步代码中的方式一样,与其他编写异步代码的方式相比,减少了很多学习成本。

Generator 为我们提供了一种更适合人脑思维方式的异步编程模型。但更好的语法也许更有帮助,在 ES7 中,一个基于 Promise 和 Generator 的异步处理函数正在规划之中,灵感来自 C# 中类似的特性。
兼容性

在服务器端,现在就可以直接在 io.js 中使用 Generator(或者在 NodeJs 中以 --harmony 启动参数来启动 Node)。

在浏览器端,目前只有 Firefox 27 和 Chrome 39 以上的版本才支持 Generator,如果想直接在 Web 上使用,你可以使用 Babel 或 Google 的 Traceur 将 ES6 代码转换为 Web 友好的 ES5 代码。

一些题外话:JS 版本的 Generator 最早是由 Brendan Eich 实现,他借鉴了 Python Generator的实现,该实现的灵感来自 Icon,早在 2006 年的 Firefox 2.0 就吸纳了 Generator。但标准化的道路是坎坷的,一路下来,其语法和行为都发生了很多改变,Firefox 和 Chrome 中的 ES6 Generator 是由 Andy Wingo 实现 ,这项工作是由 Bloomberg 赞助的。
yield;

关于 Generator 还有一些未提及的部分,我们还没有涉及到 .throw() 和 .return() 方法的使用,.next() 方法的可选参数,还有 yield* 语法。但我认为这篇文章已经够长了,就像 Generator 一样,我们也暂停一下,另外找个时间再剩余的部分。

我们已经介绍了 ES6 中两个非常重要的特性,那么现在可以大胆地说,ES6 将改变我们的生活,看似简单的特性,却有极大的用处。

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgdwjg.html