Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/442.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 避免并行异步任务中的冗余_Javascript_Node.js_Asynchronous_Parallel Processing - Fatal编程技术网

Javascript 避免并行异步任务中的冗余

Javascript 避免并行异步任务中的冗余,javascript,node.js,asynchronous,parallel-processing,Javascript,Node.js,Asynchronous,Parallel Processing,我目前正在用Node.js编写一个小应用程序,帮助我编辑和编译一些自定义文件格式。我的问题是,我有很多异步调用来读取目录、执行XHR请求或执行某些子进程,但必须避免并行处理这些任务 在这个例子中,我有一个向服务器询问目录内容的按钮:如果我快速点击这个按钮,它会多次发送相同的请求并接收相同的响应。如果一旦触发一个请求,所有其他相同的请求都会“等待”公共结果,这会更好 我正在使用,并试图找到一个函数来完成它,但我无法发现它。我还搜索了Google&Stack Overflow,但没有令人满意的答案—

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

在这个例子中,我有一个向服务器询问目录内容的按钮:如果我快速点击这个按钮,它会多次发送相同的请求并接收相同的响应。如果一旦触发一个请求,所有其他相同的请求都会“等待”公共结果,这会更好

我正在使用,并试图找到一个函数来完成它,但我无法发现它。我还搜索了Google&Stack Overflow,但没有令人满意的答案——我真的不知道如何“命名”这个问题

过去我使用过这种形式的解决方案,但我觉得肯定有更好的方法:

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 promise;

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

这是因为承诺的结果可以通过
访问,然后可以通过
访问任意次数。如果在异步调用仍在等待时“thing”再次发生,则
promise
将存在,并且您无需创建它。否则,创建一个新的,一旦任务完成就会自动删除。

我阅读了Promise doc和greim的实现,但由于我对它不太熟悉(也不太清楚“轮询”主要对象的事件部分),我找到了一个简单的解决方案来完成我的最后一个主张:

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 ;
        }) ;
    }
}
var oneTaskCallbacks={};
oneTask=功能(需求ID、cb、任务){
如果(!oneTaskCallbacks[reqId]){
oneTaskCallbacks[reqId]=[];
oneTaskCallbacks.busy=false;}
var cur=oneTaskCallbacks[reqId];
电流推力(cb);
如果(!当前正忙){
cur.busy=true;
任务(功能(错误、重复){
var cb;

对于(var i=0;isounds就像你只需要一个客户端响应缓存…我在收到答案后缓存我能缓存的内容,但这并不总是可能的。通过刷新按钮获取目录的内容,目的是绕过缓存,但不需要在第一个请求未完成时多次绕过缓存。这很公平。你仍然可以修复它在ajax调用结束时,客户端可以禁用按钮。这也可以在node中完成,但我担心这会增加不必要的复杂性/限制来正确执行。我的问题是:如何正确禁用此按钮。(该按钮只是一个简单的例子,我之所以发布,特别是因为这些快速异步调用是由我无法访问的其他代码执行的)您需要一个名为isBusy的公共可访问布尔值。您在发出请求时将isBusy设置为true,在响应时将其设置为false。在发出请求的部分,首先询问(!isBusy)…您还可以将这些部分中的html属性更新为button.diabled=true您正在阻止的任何内容。谢谢,我可以改进以前的代码,但仍在寻找更好的代码。我从未真正尝试过承诺,因此我将阅读MDN并尝试您的答案。
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 ;
        }) ;
    }
}