ES6 异步生成器结果
ES6 asynchronous generator result
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);
}
有一个异步函数的提议 return 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;
}
}
它是什么return?是Promise<Iterator<Item>>
吗? Iterator<Promise<Item>>
?还有别的吗?我该如何食用它?我想应该有一个相应的 for
循环,它将异步迭代其结果,例如:
for (await let x of ag(10)) {
console.log(x);
}
等待每个项目可用,然后再尝试访问下一个。
只是想:
Iterator-functions 没有 return-value,所以让它们异步是没有意义的。
这两种方法之间存在概念上的差距。
- 迭代器是 pull-based:您调用迭代器并调用新值的计算
- Promise 是 push-based:Promise 将结果推送给它的侦听器。 (一次或从不)
虽然在某些情况下创建一个 Iterator<Pomise<Item>>
是有意义的
function* f(g){
for(...){
let y = await g();
yield y;
}
}
我想不出任何情况下将 Iterator 包装到 Promise 中是有意义的。因为从它的定义中实例化迭代器没有任何异步。
Promise<Iterator<Item>>
或 Iterator<Promise<Item>>
?
都没有。它仍未获得批准,但当前实施 return 其他。克里斯·科瓦尔 written an about async generators, and references Jafar Husain's AsyncGenerator proposal for ES7. EDIT: We have tc39 proposal and 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>>
都不合适。当前异步生成器 return AsyncIterator
s 改为:
interface AsyncIterator<T> {
Promise<Iteration<T>> next();
}
这完全有道理。移动到迭代器的下一个元素是异步操作,这完全可以像我们想要的那样使用。
如何使用异步生成器?
Babeljs.io 已经编译了异步生成器。 Babeljs.io/repl example:
编辑:自 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 iteration 中描述):
for await (let line of readLines(filePath)) {
print(line);
}
更新:
不幸的是,async-await
没有成为 ECMAScript 2016 的一部分。至少 await
提到了一个保留字供将来使用。
更新:
相关提案:
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);
}
有一个异步函数的提议 return 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;
}
}
它是什么return?是Promise<Iterator<Item>>
吗? Iterator<Promise<Item>>
?还有别的吗?我该如何食用它?我想应该有一个相应的 for
循环,它将异步迭代其结果,例如:
for (await let x of ag(10)) {
console.log(x);
}
等待每个项目可用,然后再尝试访问下一个。
只是想: Iterator-functions 没有 return-value,所以让它们异步是没有意义的。 这两种方法之间存在概念上的差距。 - 迭代器是 pull-based:您调用迭代器并调用新值的计算 - Promise 是 push-based:Promise 将结果推送给它的侦听器。 (一次或从不)
虽然在某些情况下创建一个 Iterator<Pomise<Item>>
function* f(g){
for(...){
let y = await g();
yield y;
}
}
我想不出任何情况下将 Iterator 包装到 Promise 中是有意义的。因为从它的定义中实例化迭代器没有任何异步。
Promise<Iterator<Item>>
或 Iterator<Promise<Item>>
?
都没有。它仍未获得批准,但当前实施 return 其他。克里斯·科瓦尔 written an about async generators, and references Jafar Husain's AsyncGenerator proposal for ES7. EDIT: We have tc39 proposal and 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>>
都不合适。当前异步生成器 return AsyncIterator
s 改为:
interface AsyncIterator<T> {
Promise<Iteration<T>> next();
}
这完全有道理。移动到迭代器的下一个元素是异步操作,这完全可以像我们想要的那样使用。
如何使用异步生成器?
Babeljs.io 已经编译了异步生成器。 Babeljs.io/repl example:
编辑:自 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 iteration 中描述):
for await (let line of readLines(filePath)) {
print(line);
}
更新:
不幸的是,async-await
没有成为 ECMAScript 2016 的一部分。至少 await
提到了一个保留字供将来使用。
更新:
相关提案: