ES6生成器:将回调转换为迭代器 [英] ES6 generators: transforming callbacks to iterators

查看:68
本文介绍了ES6生成器:将回调转换为迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 babel 的帮助下尝试使用ES6生成器,但是我很难理解如何(或是否! )我可以有效地使用基于回调的异步函数来输出迭代器.

I'm experimenting with ES6 generators with the help of babel, and I have trouble understand how (or if!) I can effectively use callback based async function to output an iterator.

比方说,我希望能够编写一个函数,该函数接受多个url,异步下载它们,并在下载后立即返回它们. 我希望能够编写如下内容:

Let's say I want be able to write a function that takes a number of urls, asynchronously download them and returns them as soon as they are downloaded. I would like to be able to write something like the following:

let urls = ['http://www.google.com', 'http://www.stackoverflow.com' ];
for ( {url, data} of downloadUrls(urls) ) {
    console.log("Content of url", url, "is");
    console.log(data);
}

如何实现downloadUrls? 理想情况下,我希望能够编写以下内容:

How can I implement downloadUrls ? Ideally I would like to be able to write the following:

var downloadUrls = function*(urls) {
    for( let url of urls ) {
        $.ajax(url).done( function(data) {
            yield data;
        });
    }
};

这当然是行不通的,因为``yield''是在回调内部而不是在生成器内部直接调用的. 我可以在网上找到许多尝试相同方法的示例,它们要么不够透明),但要求启用浏览器/节点标志,或使用特定于节点的功能/库. 最接近我需要的库似乎是 task.js ,但是我什至无法运行最简单的示例在当前的Chrome上.

This of course doesn't work, since ``yield'' is being invoked inside a callback and not directly inside the generator. I can find many examples online of people trying the same, they are either not much transparent), require enabling browser/node flags, or use node-specific features/libraries. The library closest to what I need seems to be task.js, but I'm unable to have even the simplest example run on current Chrome.

是否有一种使用标准功能和当前功能来获得预期行为的方法,(当前,我的意思是可与babel等编译器一起使用,但无需在浏览器上启用额外的标志)还是必须等待?

Is there a way to get the intended behaviour using standard and current features , (With current I mean usable with transpilers like babel, but without the need to enable extra flags on the browser) or do I have to wait for async/await ?

推荐答案

2019更新

通过回调来产生实际上非常简单.由于您只能直接从生成器出现的生成器function*中调用yield(而不是从回调函数中),因此您需要产生一个Promise,它将在回调函数中成为resolve d:

2019 update

Yielding via callbacks is actually pretty simple. Since you can only call yield directly from the generator function* where it appears (and not from callbacks), you need to yield a Promise instead, which will be resolved from the callback:

async function* fetchUrls(urls) {
  for (const url of urls)
    yield new Promise((resolve, reject) => {
      fetch(url, { mode: 'no-cors' }).then(response => resolve(response.status));
    });
}

(async function main() {
  const urls = ['https://www.ietf.org/rfc/rfc2616.txt', 'https://www.w3.org/TR/PNG/iso_8859-1.txt'];
  // for-await-of syntax
  for await (const status of fetchUrls(urls))
    console.log(status);
}());

如果该示例在浏览器中不起作用(由于 repl上进行尝试.它.

If the example doesn't work in the browser (it my return 0 instead of 200 due to Cross Origin Read Blocking), try it live on repl.it.

这篇关于ES6生成器:将回调转换为迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆