避免并行异步任务的冗余

时间:2014-07-12 17:24:32

标签: javascript node.js asynchronous parallel-processing

我目前正在用Node.js编写一个小应用程序来帮助我编写和编译一些自定义文件格式。我的问题是我有很多异步调用来读取目录,执行XHR请求或执行一些子进程,但这些任务必须避免并行处理。

在示例中,我有一个按钮向服务器询问目录的内容:如果我快速点击此按钮,它会多次发送相同的请求并收到相同的响应。如果一个请求被触发,所有其他相同的请求"等待"会更好。为了共同的结果。

我正在使用Async lib,并试图找到一个功能,但我无法发现它。我还搜索了Google& Stack Overflow但没有令人满意的答案 - 我真的不知道如何" name"这个问题。

过去我使用过这种形式的解决方案,但我觉得这当然是一种更好的方式:

var requesting = false ;
var callbacks = [] ;

var request = function ( target , cb ){
    callbacks.push(cb) ;
    if ( ! requesting ) {
        requesting = true ;
        asyncTask( target , function(err,resp){
            requesting = false ;
            for (var i=0,c=callbacks.length;i<c;i++) {
                callbacks[i](err,resp) ;
            }
        }) ;
    }
}


request( "/dirA" , function(err,resp){ ... } ) ;
request( "/dirA" , function(err,resp){ ... } ) ; //Ok, avoinding redundant code
request( "/dirB" , function(err,resp){ ... } ) ; //Problem -> You can use only one target

我正在搜索一般实现,可能允许轻量级使用。也许是这样的:

var request = function ( target , cb ){
    avoidRedundancy( target , cb , function(){
        asyncTask( target , function(err,resp){
            //And now, how do I return the response ?
        }) ;
    }) ;
}
//avoidRedundancy( requestIdentifier , callback , taskToExecute )

由于

2 个答案:

答案 0 :(得分:1)

这是一个使用通用代码的模式,它使用承诺来分享共同的结果,就像您要求的那样。

var promise;

emitter.on('thing', function(){
  if (!promise){
    promise = doSomethingAsync();
    promise.then(function(){
      promise = undefined;
    });
  }
  promise.then(function(result){
    // do something with result
  });
});

这是有效的,因为可以通过then多次访问承诺的结果。如果&#34;事情&#34;当异步调用仍在等待时再次发生,然后promise将存在并且您不需要创建它。否则,创建一个在任务完成后自行删除的新文件。

答案 1 :(得分:0)

我阅读了Promise doc和greim的实现,但由于我不熟悉它(并且不确定事件部分“污染”主要对象),我找到了一个简单的解决方案来完成我的最后一个命题:< / p>

var oneTaskCallbacks = {} ;
oneTask = function( reqId  , cb , task ){
    if ( !oneTaskCallbacks[reqId]) {
        oneTaskCallbacks[reqId] = [] ;
        oneTaskCallbacks.busy = false ;}
    var cur = oneTaskCallbacks[reqId] ;
    cur.push(cb) ;
    if (!cur.busy) {
        cur.busy = true ;
        task(function(err,rep){
            var cb ;
            for (var i=0;i<cur.length;i++) {
                cb = cur[i] ;
                cb && cb.apply(null,arguments) ;}
            cur.splice(0,cur.length);
            cur.busy=false ;
        }) ;
    }
}

它只是要求一个唯一的字符串来标识任务(即要加载的节点的ID),注册回调并使用单个参数触发任务:返回回调以回答答案。