【问题标题】:Nodejs callback next loop when function is finished函数完成时Nodejs回调下一个循环
【发布时间】:2016-02-09 09:57:24
【问题描述】:

假设我们有一个脚本将为数组中的每一行执行特定任务。

function execute(err, array){
    loop(array, function(err,object){
         console.log(object)
         //do a certain task when it's finished get into the next object successively.
    });
}

function loop(array,callback){
    array.forEach(function(object){
         callback(null, object);
    });
}

function array(callback){
     callback(null, [1, 2, 3, 4, 5]);
}

setTimeout(function(){
    array(execute); 
}, 6000);

问题:

  • 如何完成任务才进入下一个循环?
  • 我的函数被认为是异步的吗?

【问题讨论】:

    标签: javascript node.js loops foreach


    【解决方案1】:

    你可以做这样的事情来迭代你的数组:

    var myarray = [1,2,3,4,5];
    next(myarray, 0);
    
    function next(array, idx) {
        if (idx !== array.length) {
            // do something
            console.log(array[idx]);
    
            // run other functions with callback
            another_fct(array[idx], function() {
                next(array, idx + 1); // then the next loop
            });
    
            // or run directly the next loop
            next(array, idx + 1);
         } else {
            // the entire array has been proceed
            console.log('an array of '+array.length+' number of elements have been proceed');
        }
    }
    
    function another_fct(array_element, callback) {
        // do something with array_element
        console.log('value : '+array_element);
        callback(); // run the next loop after processing
    }
    

    此方法将同步执行您的数组元素。

    【讨论】:

    • 我想你的意思是next(myarray, idx + 1)
    【解决方案2】:

    试试这个:

    function execute(err, array) {
        loop(array, function(err, object, next) {
             console.log(object);
             next(); // this will call recur inside loop function
        }, function() {
             console.log('All done');
        });
    }
    
    function loop(array, callback, finish) {
        var copy = array.slice();
        (function recur() {
            var item = copy.shift();
            if (item) {
                callback(null, item, recur);
            } else {
                if (typeof finish == 'function') { 
                    finish();
                }
            }
        })();
    }
    

    不,您的函数不是异步的,而是使用 setTimeout 异步调用它。

    【讨论】:

    • 如何验证这一点,因为输出几乎是即时的?
    • @AlessandroGenovese 你可以在 setTimeout 中调用 next()
    • 完美,这个答案建议使用同步方法:stackoverflow.com/questions/32159018/… 可以吗?而不是只使用 settimeout?
    • @AlessandroGenovese 不知道。
    • @AlessandroGenovese 您在回调中执行此操作,recur 仅用于遍历数组。
    【解决方案3】:

    async 为此提供了 async.series 和其他帮助程序。

    【讨论】:

      【解决方案4】:

      如果您重构代码并删除任何多余的匿名函数,您可以更好地理解它。情况是,将匿名函数作为参数传递给另一个函数还没有使函数异步。您在"Does taking a callback make a function asynchronous?" 中阅读了更多更深入的解释。

      从重构版本开始,

      setTimeout(function() {
          [1, 2, 3, 4, 5].forEach(function(object) {
              console.log(object)
              //do a certain task when it's...
          });
      }, 6000);
      

      可以看出,数组调用了forEachforEach 方法对每个数组元素执行一次提供的函数并同步执行。

      所以,回答你的问题:

      1. 是的,它仅在完成前一项后才调用下一项(但如果执行任何异步操作,请参见下文)
      2. 这不被认为是异步的,因为它不执行任何异步操作(不考虑外部setTimeout

      但是,如果您选择在forEach 函数中启动异步 操作,那么情况就会发生很大变化。结果是所有操作同时进行。这在资源方面是潜在的危险操作。有诸如 async 之类的库可以优雅地处理这个用例。

      (顺便说一句,很好地使用 Node.js errbacks,其中第一个函数参数保留用于传递潜在错误。)

      【讨论】:

      • 对异步和同步操作有一个误解,我正在深入了解它。是的,我正在尝试尽可能多地使代码干净,使用回调以便将来进行轻松修改,但是你能问一下为什么在函数上使用 settimeout 会使其异步吗?
      • 这很棘手,而且肯定有一点学习曲线。因此异步操作是利用主机系统并导致稍后调用回调函数而不是直接调用它(=同步)。 setTimeout 是一个异步函数——它接受一个回调和一个毫秒值,并在超时过后触发回调。顺便说一句,Node.js 会在等待时间内进行其他事情,如果效率很高的话。
      猜你喜欢
      • 2017-06-02
      • 1970-01-01
      • 2021-05-28
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-27
      • 1970-01-01
      相关资源
      最近更新 更多