ES6有generators that return iterators:
function* range(n) {
for (let i = 0; i < n; ++i) {
yield i;
}
}
for (let x of range(10)) {
console.log(x);
}
有一个返回Promises的异步函数的提议:
async function f(x) {
let y = await g(x);
return y * y;
}
f(2).then(y => {
console.log(y);
});
如果我将两者结合起来会发生什么,例如:
async function* ag(n) {
for (let i = 0; i < n; ++i) {
yield i;
}
}
它返回什么?是Promise<Iterator<Item>>
吗? Iterator<Promise<Item>>
?别的什么?我该如何食用?我想应该有一个相应的for
循环,它会异步迭代它的结果,如:
for (await let x of ag(10)) {
console.log(x);
}
等待每个项目在尝试访问下一个项目之前可用。
答案 0 :(得分:5)
Promise<Iterator<Item>>
或Iterator<Promise<Item>>
?都不是。它仍然没有被批准,但是当前的实现还会返回其他内容。 Kris Kowal有written an about async generators,参考Jafar Husain's AsyncGenerator proposal for ES7。 编辑:我们有tc39 proposal和babel support!
让我们定义一些类型(简化):
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);
}
}
Iterator<Promise<T>>
生成同步迭代,其值为Promises。它可以像这样使用:
for (;;) {
var iteration = iterator_promise.next();
if (iteration.done) {
return await iteration.value;
} else {
console.log(await iteration.value);
}
}
Promise<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
:
interface AsyncIterator<T> {
Promise<Iteration<T>> next();
}
这完全有道理。移动到迭代器的下一个元素是异步操作,这可以像我们想的那样使用。
Babeljs.io已经编译了异步生成器。 Babeljs.io/repl example 秒>:
编辑:babeljs.io上没有预设编译异步生成器,因为babel 6,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 iteration中描述):
for await (let line of readLines(filePath)) {
print(line);
}
<强>更新强>
不幸的是,async-await
并未成为ECMAScript 2016的一部分。至少await
被提及为将来使用的保留字。
<强>更新强>
相关提案:
答案 1 :(得分:0)
想一想: 迭代器函数没有返回值,因此将它们设置为异步毫无意义。 那么这两种方法之间存在这种概念上的差距。 - 迭代器是基于拉取的:你调用迭代器并调用新值的计算 - Promise是基于推送的:Promise将结果推向了它的倾听者。 (曾经或从未)
虽然在某些情况下会创建一个Iterator<Pomise<Item>>
function* f(g){
for(...){
let y = await g();
yield y;
}
}
我无法想到将Iterator包装成Promise是有意义的。因为从它的定义中实例化Iterator没有任何异步。