async.series的第一个参数耗时太长会阻塞?
发布于 9 年前 作者 cheergoh 4631 次浏览 最后一次编辑是 8 年前 来自 问答

如图 测试发现如果query.exec()中执行耗时的操作,基本上等于没有异步处理,一个请求需要10秒,两个请求就需要20秒。 这是为什么? untitled4.png

18 回复

异步接受io请求,后台同步处理?

async.series就是顺序执行的啊,一个执行完成后才执行下一个,所以时间会累加起来:

Run the functions in the tasks array in series, each one running once the previous function has completed. 

摘自github的说明:https://github.com/caolan/async#seriestasks-callback

@crystaldust 他这儿是一个function里面

@20082496 嗯,不好意思没看仔细。但是这样的话,执行整个流程,10秒应该就结束了。楼主你说的“两个请求就需要20秒”是指什么情况呢?

@crystaldust 比如说同时发起3个请求,这里有个10秒的等待,第一个请求是10秒后获取到数据,第二个请求就是20秒后获取到数据,第三个就是30秒。就是这样

@20082496 按理说10个并发就是10个请求每个都要等十秒,但是这里是需要累加等待的,10,20,30… 最后一个是100秒后才能拿到数据。

@cheergoh 楼主你的代码提炼一下是不是这个意思:

var async = require( 'async' );

function api( callback ) {
  async.series( {
    one : function( cb ) {
      setTimeout( function() {
        cb( null, 'hello' );
      } , 10000 );
    }
  }, function( err, result ) {
    callback( result );
  } );
}

// Call the API 3 times
var n = 0;
var start_ms = new Date().getTime()
for(var i=0; i<3; ++i ) {
  api( function( result ) {
    console.log( result );
    if( ++n >= 3 ) {
      console.log( 'ms: ', new Date().getTime() - start_ms );
      process.exit( 0 );
    }
  } );
}

我这测试最终打印的时间是10031毫秒,结果和预期的10秒是一致的啊

@cheergoh 请求不是并发的么,为什么会顺序…

@20082496 如果真是这样,他怎么做到的…

@crystaldust 可能是我的写法有问题啊 , 发给你看看 untitled1.png

@DevinXian 是并发的啊,但是服务器接受到请求总会有先后,发了截图了,可能是我用时间的关系

@cheergoh 我的神哪,sleep!CPU都在sleep中煎熬…

setTimeout会占用cpu,导致事件轮询阻塞

楼主应该没搞清楚async是用来干嘛的。。。

杭州大搜车(C轮)诚意求才(NodeJS服务端开发) http://t.cn/R2NXqK7

@cheergoh 如果我没有理解错你的意思的话,那就是你理解错异步了。

query.exec(function(err, list){
	sleep(10000);
	cb(err,list);
})

上面的代码是在主线程里同步执行的,如果你在javascript代码里有耗时操作,那就是实实在在的耗时,javascript内的任何代码都是同步执行的,绝对不会异步执行。javascript代码只能发起异步命令,这个异步命令发布完成后,程序不是傻等, 而是去处理已完成的异步请求。所以按照这个解释,你最后一个回复当然会消耗100秒。发起异步命令和异步完成后的回调时间我们假设很短,忽略不计,你发出了10条异步请求,等待回复,最快的情况我们假设是立即返回,异步处理时间也忽略不计,你发出的异步请求随即的返回了,由于是并行的,完成的先后顺序不确定,顺序其实不是关键,接下来我们来处理数据,在主线程内,我们先处理第一个10秒,完成后发送数据,第二个开始处理就是从第一个完成开始的,以此类推,最后一个耗时就是100秒。

千万不要以为回调里面代码是异步执行的,回调是同步执行的,回调执行的时候,异步请求已经结束了。javascript代码永远是同步的,里面耗时的计算是实打实的。

@coordcn 大哥,每次都看到你这么详细耐心而且深入的回答别人的问题,请收下我的膝盖 XD

@cheergoh 15楼的大哥已经解释的很清楚了

@coordcn 多谢大神耐心指点,我自己想根本不能理解。感动哭 T_T

回到顶部