javascript - 由于异步生成器中的 promise 的非并行等待而导致速度减慢

标签 javascript async-await promise generator bluebird

我正在使用生成器和 Bluebird 编写代码,并且我有以下内容:

var async = Promise.coroutine;
function Client(request){
    this.request = request;
}


Client.prototype.fetchCommentData = async(function* (user){
    var country = yield countryService.countryFor(user.ip);
    var data = yield api.getCommentDataFor(user.id);
    var notBanned = yield authServer.authenticate(user.id);
    if (!notBanned) throw new AuthenticationError(user.id);
    return {
        country: country,
        comments: data,
        notBanned: true
    };
});

但是,这有点慢,我觉得我的应用程序等待 I/O 的时间太多,而且它不是并行的。如何提高应用程序的性能?

countryFor 的总响应时间为 800,getCommentDataFor 为 400,authenticate 为 600,所以总共 1800 毫秒,这是很多。

最佳答案

您花费了太多时间等待来自不同来源的 I/O。

在正常的 Promise 代码中,您可以使用 Promise.all 来实现此目的,但是 - 人们倾向于编写等待生成器请求的代码。您的代码执行以下操作:

<-client     service->
countryFor..
           ''--..
              ''--..
                 ''--.. country server sends response
               ..--''
          ..--''
     ..--''
getCommentDataFor
     ''--..
           ''--..
               ''--..
                     ''--.. comment service returns response
                ..--''
          ..--''
      ..--''
authenticate
       ''--..
            ''--..
                  ''--.. authentication service returns
             ..--''
       ..--''
 ..--''
 Generator done.

相反,它应该这样做:

<-client     service->
countryFor..
commentsFor..''--..
authenticate..''--..''--..
                 ''--..''--..''--.. country server sends response
                        ''--..--''..  comment service returns response
                   ..--''..--''..     authentication service returns response
          ..--''..--''..
 ..--''..--''..--''
 ..--''..--''
 ..--''
 Generator done

简单地说,所有 I/O 都应该在这里并行完成。

要解决此问题,我将使用 Promise.propsPromise.props 获取一个对象并等待其所有属性解析(如果它们是 Promise)。

记住 - 生成器和 Promise 混合并匹配真的很好,你只需产生 Promise:

Client.prototype.fetchCommentData = async(function* (user){
    var country = countryService.countryFor(user.ip);
    var data = api.getCommentDataFor(user.id);
    var notBanned = authServer.authenticate(user.id).then(function(val){
          if(!val) throw new AuthenticationError(user.id);
    });
    return Promise.props({ // wait for all promises to resolve
        country : country,
        comments : data,
        notBanned: notBanned
    });
});

这是人们第一次使用生成器时经常犯的错误。

ascii 艺术无耻地取自 Kris Kowal 的 Q-Connection

关于javascript - 由于异步生成器中的 promise 的非并行等待而导致速度减慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28891331/

相关文章:

javascript - Angular - 如何通过路由器将信息传递到 Controller ?

c# - 如何在 C# 中创建和使用自定义 Awaitable?

node.js - NodeJS : Are callback functions or synchronous functions better to use in async/await?

javascript - 在 React 渲染中循环动态服务器响应

javascript - 将变量传递给 C# 代码中的 javascript 函数

javascript - Gmaps4rails : How to change appearance of marker when user clicks link in sidebar?

mysql - nodejs Promises操作中的事务管理

javascript - 与 promise 一起工作,做一个储蓄

javascript - 如何在 TypeScript 中使用泛型模拟 Java 类文字?

asynchronous - 如何接受异步函数作为参数?