- 原文地址:Javascript – Generator-Yield/Next & Async-Await
- 原文作者:Deepak Gupta
- 译文出自:掘金翻译计划
- 本文永久链接:github.com/xitu/gold-m…
- 译者:iceytea
- 校对者:huimingwu, zsky
Generator (ES6)
generator 函数是一个可以根据用户需求,在不同的时间间隔返回多个值,并能管理其内部状态的函数。如果一个函数使用了 function* 语法,那么它就变成了一个 generator 函数。
它们与正常函数不同,正常函数在单次执行中完成运行,而 generator 函数可以被暂停和恢复。它们确实会运行完成,但触发器在我们手中。它们使得对异步函数能有更好的执行控制,但这并不意味着它们不能用作同步函数。
注意:执行 generator 函数时,会返回一个新的 Generator 对象。
generator 的暂停和恢复是使用 yield
和 next
完成的。让我们来看看它们是什么,以及它们能做什么。
Yield/Next
yield
关键字暂停 generator 函数的执行,并且yield
关键字后面的表达式的值将返回给 generator 的调用者。它可以被理解为基于 generator 版本的return
关键字。
yield
关键字实际上返回一个具有 value
和 done
两个属性的 IteratorResult
对象。(如果你不了解什么是 iterators 和 iterables,点击这里阅读)。
一旦暂停
yield
表达式,generator 的代码执行将保持暂停状态,直到调用 generator 的next()
方法为止。每次调用 generator 的next()
方法时,generator 都会恢复执行并返回 iterator 结果。
嗯……理论先到这里,让我们看一个例子:
function* UUIDGenerator() {
let d, r;
while(true) {
yield 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
r = (new Date().getTime() + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c=='x' ? r : (r&0x3|0x8)).toString(16);
});
}
};
UUIDGenerator 是一个 generator 函数,它使用当前时间和随机数计算 UUID ,并在每次执行时返回一个新的 UUID 。
要运行上面的函数,我们需要创建一个可以调用 next()
的 generator 对象:
const UUID = UUIDGenerator();
// UUID is our generator object
UUID.next()
// return {value: 'e35834ae-8694-4e16-8352-6d2368b3ccbf', done: false}
每次 UUID.next() 返回值的 value 值是新的 UUID ,done 值将始终为 false ,因为我们处于一个无限循环中。
注意:我们在无限循环上暂停,这是一种很酷的方式。在 generator 函数中的任何“停止点”处,不仅可以为外部函数生成值,还可以从外部接收值。
有许多 generator 的实现,并且很多库都在大量使用。比如说 co、koa 和 redux-saga。
Async/Await (ES7)
依照惯例,当一个异步操作返回由 Promise
处理的数据时,回调会被传递并调用。
Async/Await 是一种特殊的语法,以更舒适的方式使用 Promise,这种方式非常容易理解和使用。
Async 关键字用于定义异步函数 ,该函数返回一个 AsyncFunction 对象。
Await 关键字用于暂停异步函数执行,直到 Promise
被解决(resolved 或者 rejected),并在完成后继续执行 async
函数。恢复时,await 表达式的值是已执行的 Promise 的值。
关键点:
- Await 只能在异步函数中使用。
- 具有 async 关键字的函数将始终返回 promise。
- 在相同函数下的多个 await 语句将始终按顺序运行。
- 如果 promise 正常被 resolve,则
await
会返回promise
结果。但是如果被 reject,它就会抛出错误,就像在那行有throw
语句一样。- 异步函数不能同时等待多个 promise。
- 如果在 await 之后使用 await 多次,并且后一条语句不依赖于前一条语句,则可能会出现性能问题。
到目前为止一切顺利,现在让我们看一个简单的例子:
async function asyncFunction() {
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("i am resolved!"), 1000)
});
const result = await promise;
// wait till the promise resolves (*)
console.log(result); // "i am resolved!"
}
asyncFunction();
在 await promise
这一行,asyncFunction
执行“暂停”,并在 promise 被解决后回复,result
(第 95 行的 const result
)变成它的结果。上面的代码在一秒钟后展示 “i am resolved!
”。
Generator 和 Async-await 比较
- Generator 函数/yield 和 Async 函数/await 都可以用来编写“等待”的异步代码,这意味着代码看起来像是同步的,即使它确实是异步的。
- Generator 函数按照 yield 接着 yield 的顺序执行,就是说一个 yield 表达式通过迭代器来执行一次(执行
next
方法),而 Async-await 按照 await 接着 await 的顺序依序执行。 - Async/await 可以更容易地实现 Generators 的特定用例。
- Generator 的返回值始终是 {value: X, done: Boolean}。对于 Async 函数它将始终是一个将解析为值 X 或抛出错误的 promise。
- Async 函数可以分解为 Generator 和 promise 来实现,这些都很有用。
如果您想要添加到我的电子邮件列表中,请考虑 在此处输入您的电子邮件,并在 medium 上关注我以阅读更多有关 javascript 的文章,并在 github 上查看我的疯狂代码。如果有什么不清楚的,或者你想指出什么,请在下面评论。
你可能也喜欢我的其他文章:
- Nodejs app structure
- Javascript data structure with map, reduce, filter
- Javascript- Currying VS Partial Application
- Javascript ES6 — Iterables and Iterators
- Javascript performance test — for vs for each vs (map, reduce, filter, find).
- Javascript — Proxy
如果你喜欢这篇文章,请鼓掌。提示:你可以拍 50 次!此外,欢迎推荐和分享,以帮助其他人找到它!
谢谢!
如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。
今天的文章[译] JavaScript – Generator-Yield/Next 和 Async-Await分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/15371.html