由于异步生成器中的 promise 的非并行等待而导致减速 [英] Slowdown due to non-parallel awaiting of promises in async generators

查看:9
本文介绍了由于异步生成器中的 promise 的非并行等待而导致减速的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing code using generators and Bluebird and I have the following:

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 的时间太多,而且不是并行的.如何提高应用程序的性能?

However, this is kind of slow, I feel like my application is waiting too much for I/O and it's not in parallel. How can I improve the performance of my application?

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

The total response time is 800 for countryFor + 400 for getCommentDataFor + 600 for authenticate so in total 1800ms which is a lot.

推荐答案

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

You are spending too much time waiting for I/O from different sources.

在普通的 Promise 代码中,您会为此使用 Promise.all,但是 - 人们倾向于编写代码来等待带有生成器的请求.您的代码执行以下操作:

In normal promise code, you'd use Promise.all for this, however - people have a tendency to write code that waits for requests with generators. Your code does the following:

<-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 都应该在这里并行完成.

Simply put, all your I/O should be done in parallel here.

为了解决这个问题,我会使用 Promise.props.Promise.props 接受一个对象并等待其所有属性解析(如果它们是 Promise).

To fix this, I'd use Promise.props. Promise.props takes an objects and waits for all its properties to resolve (if they are promises).

记住 - 生成器和承诺混合和匹配真的,你只需产生承诺:

Remember - generators and promises mix and match really well, you simply yield promises:

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
    });
});

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

This is a very common mistake people make when using generators for the first time.

Kris Kowal 无耻地从 Q-Connection 中截取的 ascii 艺术

这篇关于由于异步生成器中的 promise 的非并行等待而导致减速的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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