【问题标题】:How to combine ES6 Generators with Promises如何将 ES6 生成器与 Promises 结合使用
【发布时间】:2016-02-01 17:39:17
【问题描述】:

我试图从概念上理解 ES6 生成器如何使异步代码更加精简。这是一个人为的例子:

  1. 我有一个名为 getGitHubUser 的函数,它接受用户名并返回一个最终解析为 github 用户信息的 Promise。
  2. 我有一组用户名。
  3. 我想用第一个用户名调用 getGitHubUser,当 Promise 解决后,我想用下一个用户名调用 getGitHubUser,并继续此操作,直到我遍历所有用户名。

我有一个可行的实现,但我更好奇如何利用生成器来改进它。

var getGitHubUser = (user) => {
  // using jQuery's $.get
  return Promise.resolve($.get("https://api.github.com/users/" + user));
};

var usernames = ["fay-jai", "jyek", "Maestro501", "jaclyntsui"];

getGitHubUser(usernames[0])
  .then((result) => {
    console.log(result); // fay-jai
    return getGitHubUser(usernames[1]);
  })
  .then((result) => {
    console.log(result); // jyek
    return getGitHubUser(usernames[2]);
  })
  .then((result) => {
    console.log(result); // Maestro501
    return getGitHubUser(usernames[3]);
  })
  .then((result) => {
    console.log(result); // jaclyntsui
  });

【问题讨论】:

  • 我认为生成器在这里没有任何帮助。您可以简单地遍历数组,而不是“手动”链接 .then 调用。
  • 如果每个后续结果都依赖于之前的 Promise 调用,这是真的吗?在我的示例中,我目前只是注销结果,但如果下一个 Promise 调用取决于上一个调用解析,那么我需要手动链接它,对吗?
  • 没有。示例:var p = Promise.resolve(); data.forEach(d => (p = p.then(result => someAsyncCall(d, result))));。您只需在循环中继续调用p = p.then(...)。这会将新的 Promise 链接到之前的 Promise。
  • 感谢@FelixKling 提供示例!在什么情况下生成器对异步代码有用?
  • 你可能会感兴趣:davidwalsh.name/async-generators.

标签: javascript generator ecmascript-6 es6-promise


【解决方案1】:

如果您想了解它的工作原理,请考虑good article

如果您正在寻找一些糟糕的解决方案,有很多库可以处理回调地狱(因为基本上这是人们寻找更优雅解决方案的主要原因)。

@user890255 在他的回答中已经对Q.spawn 进行了简要描述,但还有其他人。比如我最喜欢的co

var request = require('superagent');
co(function* () {
  var data = [];
  for(var i = 0; i < usernames.length; i++){
    data.push(yield request.get("https://api.github.com/users/" + usernames[i]));
  }
  return data;
}).then((value) => {
  console.log(value);
}, (err) => {
   console.error(err.stack);
});

如你所见,co 总是返回一个 promise,非常方便。

而且极简主义(我想是因为文件很小)vo

var request = require('superagent');

vo(function* () {
  var data = [];
  for(var i = 0; i < usernames.length; i++){
    data.push(yield request.get("https://api.github.com/users/" + usernames[i]));
  }
  return data;
})((err, res) => {
  console.log(res);
});

如您所见,生成器函数中的代码几乎相同。

干杯!

【讨论】:

    【解决方案2】:

    这就是您使用Q 的方式。另请阅读 Harmony generators and promises for Node.js async fun and profitJavaScript Promises

    var usernames = ["fay-jai", "jyek", "Maestro501", "jaclyntsui"];
    Q.spawn(function *(){
      var index = 0;
      while (index < usernames.length){
        console.log(yield Promise.resolve($.get("https://api.github.com/users/" + usernames[index])));
        index++;
      }
    });
    

    【讨论】:

      猜你喜欢
      • 2016-09-24
      • 2016-10-14
      • 2021-12-15
      • 2017-02-21
      • 2016-06-18
      • 2015-02-18
      • 2016-04-14
      • 2019-05-12
      • 1970-01-01
      相关资源
      最近更新 更多