Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.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 - Fatal编程技术网

Javascript 循环和回调地狱

Javascript 循环和回调地狱,javascript,node.js,Javascript,Node.js,假设您有一个包含值列表的数组/对象。让我们假设这些是mysql命令、URL或文件路径。现在,您需要迭代所有这些条目,并在每个条目上执行一些代码 for(let i = 0; i < urls.length; i++){ doSthWith(urls[i]); } 无论哪种方式,我都看不到使用循环的方法 我发现了一种方法,但不是很好,就是使用“wait.for”(等待)软件包。但是,让这个软件包变得棘手的是,每次您想使用wait时都要启动一根光纤。等待: //somewhere y

假设您有一个包含值列表的数组/对象。让我们假设这些是mysql命令、URL或文件路径。现在,您需要迭代所有这些条目,并在每个条目上执行一些代码

for(let i = 0; i < urls.length; i++){
   doSthWith(urls[i]);
}
无论哪种方式,我都看不到使用循环的方法

我发现了一种方法,但不是很好,就是使用“wait.for”(等待)软件包。但是,让这个软件包变得棘手的是,每次您想使用wait时都要启动一根光纤。等待:

 //somewhere you use the function in a fiber Context
 wait.for(loopedExecutionOfUrls, urls); 
 //function declaration
 function loopedExecutionOfUrls(urls, cb){
     //variables: 
      for(let i = 0; i < urls.length; i++){
          if(someTempResultVar[i-1] === true){ 
            someTempResultVar = wait.for(doSthWith,urls[i]);
          } else if(...){...}
      }
 }
//在光纤上下文中使用该函数的某个地方
wait.for(loopedExecutionFurls、URL);
//函数声明
函数loopedExecutionFurls(URL、cb){
//变量:
for(设i=0;i
但是我不确定这种方法是否真的很好,此外,您必须始终检查是否已将整个过程包装在一个光纤中,因此对于每个具有循环且具有回调的函数。因此,您有3个级别:laucfiber级别、wait.for(loopedFunction)级别和wait.for回调函数级别。(我希望这是可以理解的)

所以我的问题是:你们有一个好的方法,可以循环抛出回调函数,并且可以随时使用这些函数的结果吗

好=易于使用、可读、性能好、不递归


(如果这个问题很愚蠢,我很抱歉,但我在处理这个异步编程时确实遇到了问题)

如果您想等待
dosswhith
完成,然后再执行相同的操作,但是对于nex url,您必须链接您的承诺,并且您可以使用
array.prototype。reduce
来实现这一点:

URL=[“aaa”、“bbb”、“ccc”、“ddd”];
reduce((lastPromise,url)=>lastPromise.then((resultOfPreviousPromise)=>{
log(“上一个请求的结果:,resultOfPreviousPromise);//{
setTimeout(()=>resolve(“参数+arg的结果”),2000年);
});       
}
使用,特别是:


如果您对结果感兴趣,请使用。

当我需要循环承诺时,我会使用方便的dandy ploop函数。以下是一个示例:

// Function that returns a promise
var searchForNumber = function(number) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        var min = 1;
        var max = 10;
        var val = Math.floor(Math.random()*(max-min+1)+min);

        console.log('Value is: ' + val.toString());        

        return resolve(val);        
      }, 1000);
    });
};

// fn     : function that should return a promise.
// args   : the arguments that should be passed to fn.
// donefn : function that should check the result of the promise
//    and return true to indicate whether ploop should stop or not.
var ploop = function(fn, args, donefn) {
    return Promise.resolve(true)
      .then(function() {
          return(fn.apply(null, args));
      })
      .then(function(result) {
        var finished = donefn(result);
        if(finished === true){
           return result;
        } else {
          return ploop(fn, args, donefn);
        }
    });
};

var searchFor = 4;

var donefn = function(result) {
  return result === searchFor;
};

console.log('Searching for: ' + searchFor);
ploop(searchForNumber, [searchFor], donefn)
  .then(function(val) {
    console.log('Finally found! ' + val.toString());  
    process.exit(0);
  })
  .catch(function(err) {
    process.exit(1);
  });

在这种情况下,可能会重复“不确定”。我的意思是,我的问题有解决方案,但都是基于承诺的。我已经用async.each/async.map得到了答案,因为我没有特别要求承诺,而是一般要求如何处理回调和循环。不确定tho。我是否应该编辑我的问题并提及您建议的线程在编辑中?+1实际上,promises才是真正的答案。但是,请记住,如果您整体上切换到promises,这将最有效,并且promises中的错误处理可能会很棘手。例如,如果DossWith中发生错误,此程序将崩溃,因为错误案例未被处理。+1不仅有效,而且您也可以轻松修改代码,将以前的值和新的承诺一起传递给减速机(OP就是这么问的)。如果我说:url1->result1,…,url4=url4+result 1->result 4,这也行吗?就像我不需要上一个而是一个特定的?如果我有正常的函数,我可以把结果放在数组中,以后再引用特定的索引。如果我正确理解reduce,你只能访问当前和上一个索引。但是我不知道array.reduce。谢谢你告诉我它的存在。很好的递归解决方案。如果你循环超过10000次,可能不会执行。看起来是迄今为止最好的答案。易于理解和使用。
 //somewhere you use the function in a fiber Context
 wait.for(loopedExecutionOfUrls, urls); 
 //function declaration
 function loopedExecutionOfUrls(urls, cb){
     //variables: 
      for(let i = 0; i < urls.length; i++){
          if(someTempResultVar[i-1] === true){ 
            someTempResultVar = wait.for(doSthWith,urls[i]);
          } else if(...){...}
      }
 }
const async = require('async');

function doSthWith(url, cb) {
    console.log('doing something with ' + url);
    setTimeout(() => cb(), 2000);
}

const urls = ['https://stackoverflow.com/', 'https://phihag.de/'];
async.each(urls, doSthWith, (err) => {
    if (err) {
        // In practice, likely a callback or throw here
        console.error(err);
    } else {
        console.log('done!');
    }
});
// Function that returns a promise
var searchForNumber = function(number) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        var min = 1;
        var max = 10;
        var val = Math.floor(Math.random()*(max-min+1)+min);

        console.log('Value is: ' + val.toString());        

        return resolve(val);        
      }, 1000);
    });
};

// fn     : function that should return a promise.
// args   : the arguments that should be passed to fn.
// donefn : function that should check the result of the promise
//    and return true to indicate whether ploop should stop or not.
var ploop = function(fn, args, donefn) {
    return Promise.resolve(true)
      .then(function() {
          return(fn.apply(null, args));
      })
      .then(function(result) {
        var finished = donefn(result);
        if(finished === true){
           return result;
        } else {
          return ploop(fn, args, donefn);
        }
    });
};

var searchFor = 4;

var donefn = function(result) {
  return result === searchFor;
};

console.log('Searching for: ' + searchFor);
ploop(searchForNumber, [searchFor], donefn)
  .then(function(val) {
    console.log('Finally found! ' + val.toString());  
    process.exit(0);
  })
  .catch(function(err) {
    process.exit(1);
  });