Promise<Iterator<Item>>
还是Iterator<Promise<Item>>
?
两者都不。它仍未获得批准,但当前的实现会返回其他内容。Kris Kowal写了一篇关于异步生成器的文章,并参考了Jafar Husain 的 ES7 AsyncGenerator 提案。编辑:我们有tc39 提案和babel 支持!
让我们定义一些类型(简化):
interface Iterator<T> {
Iteration<T> next();
}
type Iteration<T> = { done: boolean, value: T }
我们正在寻找可以像这样使用的东西:
for (;;) {
var iteration = await async_iterator.next();
if (iteration.done) {
return iteration.value;
} else {
console.log(iteration.value);
}
}
AnIterator<Promise<T>>
产生同步迭代,其值为 Promises。它可以这样使用:
for (;;) {
var iteration = iterator_promise.next();
if (iteration.done) {
return await iteration.value;
} else {
console.log(await iteration.value);
}
}
APromise<Iterator<T>>
只是一个普通的同步迭代器,从未来开始:
var iterator = await promise_iterator;
for (;;) {
var iteration = iterator.next();
if (iteration.done) {
return iteration.value;
} else {
console.log(iteration.value);
}
}
所以既不合适Iterator<Promise<T>>
也Promise<Iterator<T>>
不合适。目前异步生成器返回AsyncIterator
s :
interface AsyncIterator<T> {
Promise<Iteration<T>> next();
}
这完全有道理。移动到迭代器的下一个元素是异步操作,这可以完全按照我们的意愿使用。
如何使用异步生成器?
Babeljs.io 已经编译了异步生成器。Babeljs.io/repl 示例:
编辑:自 babel 6 以来,babeljs.io 上没有预设编译异步生成器,通过选项babel-plugin-transform-regenerator
支持它。{asyncGenerators:true}
编辑:见transform-async-generator-functions
babel 6 插件。
function delay(timeout, val) {
return new Promise(resolve => setTimeout(resolve, timeout, val));
}
async function* asyncGenerator() {
for (var i = 0; i < 5; i++) {
await delay(500);
yield i;
}
}
async function forAwait(iter, fn) {
for (;;) {
let iteration = await iter.next();
if (iteration.done) return iteration.value;
await fn(iteration.value);
}
}
async function main() {
console.log('Started');
await forAwait(asyncGenerator(), async item => {
await delay(100);
console.log(item);
});
console.log('End');
}
main();
有一个用于异步迭代器的便捷for await
循环的提议(在Async 迭代中描述):
for await (let line of readLines(filePath)) {
print(line);
}
更新:
不幸的是,async-await
没有成为ECMAScript 2016的一部分。至少await
提到了一个保留字以备将来使用。
更新:
相关提案: