【问题标题】:combo of async map, recursion and callback in function- nodejs函数中的异步映射、递归和回调的组合-nodejs
【发布时间】:2017-05-21 06:32:18
【问题描述】:

我有一个计算一个值的函数,计算后返回一个回调到另一个函数的值。

情况开始变得非常复杂,我在其中有 2 个嵌套的 for 循环和递归。

错误是:uncaughtException: Callback was already called.

首先让我编写代码示例。

functionTest (array, function (err, result) {
  if (err) {
    nresponse.error(err);
  } else {
    nresponse.success(res, result);
  }
);

function dependicies(array, callback) {
    async.map(array, function(item, outerNext) {
        async.map(item.members, function(value, innerNext){
            dependicies(array, callback);
            innerNext(); //should I write this after or before the recursion call?
            outerNext(); //where should I call the outerNext?
        });

    }, function(err, result){
        **
        if(err){
            callback(err); 
        }else{
            callback(null, sthComputedInMap);
        }
    });
}

当我在 cmets 中编写代码时,我应该在递归调用之后还是之前编写 innerNext?除了这个问题,我应该在第二张地图的范围之后调用outerNext吗?

事情很混乱。我要怎么收拾?我在看文件。

** 这不是第一个async.map 结束的地方。我认为问题在于recursion 中的each async.map。我想要的是把它称为break

在代码中,我尝试循环遍历一个数组。假设我尝试获取一个文档的名称字段列表,从它自己开始到它的最后一个孙子。我追踪的数组结构是这样的;

[
  {id: 1, childrenIds: [3, 4, 5], name: ""},
  {id: 3, childrenIds: [8, 5], name: ""},
  {id: 21, childrenIds: [ 5], name: ""},
  {id: 7, childrenIds: [5], name: ""},
  {id: 5, childrenIds: [], name: ""}
 ]

第一个 async.map 用于遍历每个文档,另一个用于遍历其子数组。

希望对你有帮助:)

【问题讨论】:

  • 如果你能让人们更多地了解你想要实现的目标可能会有所帮助,可能只是我,但我很难理解你提到的递归,也许更多的上下文会有所帮助?
  • 代码中的递归中断在哪里。我的意思是说应该有一个条件,这样它就不会再次调用dependencies()并执行下一个Callbacks。
  • @OliverRadini 好的,我会尝试的。请等待更新。
  • @FarooqKhan 我根据您的评论编辑了问题。
  • @OliverRadini 我添加了

标签: javascript node.js asynchronous recursion callback


【解决方案1】:

您可以使用SynJS 混合循环、递归和回调。下面是一个工作示例来说明。 setTimeout 只是作为异步函数的一个例子,通过回调返回结果。

global.SynJS = global.SynJS || require('synjs');

function processOneDoc(modules, documents, doc, childNames) {
    for(var i=0; doc.childrenIds && i < doc.childrenIds.length; i++) {
        var currDoc = documents[doc.childrenIds[i]];
        if(currDoc) {
            childNames.push(currDoc.name);
            var chNames=[];
            setTimeout(function(){
                SynJS.run(modules.processOneDoc, null, modules, documents, currDoc, chNames, function(){
                    SynJS.resume(_synjsContext);
                });
                if(chNames.length)
                    childNames.push(chNames);
            },2000);
            SynJS.wait();
        }
    }
};

function processAll(modules, documents) {
    for(var d in documents) {
        var childNames=[];
        SynJS.run(modules.processOneDoc,null, modules, documents, documents[d], childNames,function(){
            SynJS.resume(_synjsContext);
        });
        SynJS.wait();
        console.log(new Date().toISOString(), d, childNames);
    }
}

var modules = {
        SynJS:  SynJS,
        processOneDoc: processOneDoc,
};

var documents = {
                 1: {id: 1, childrenIds: [3, 4, 5], name: "name of 1st"},
                 3: {id: 3, childrenIds: [8, 5], name: "name of 3rd"},
                 21: {id: 21, childrenIds: [ 5], name: "name of 21st"},
                 7: {id: 7, childrenIds: [5], name: "name of 7th"},
                 5: {id: 5, childrenIds: [], name: "name of 5th"}
};

SynJS.run(processAll,null,modules,documents,function () {
    console.log('done');
});

它将产生以下输出:

2017-01-06T18:50:57.750Z 1 [ 'name of 3rd', [ 'name of 5th' ], 'name of 5th' ]
2017-01-06T18:50:59.785Z 3 [ 'name of 5th' ]
2017-01-06T18:50:59.800Z 5 []
2017-01-06T18:51:01.831Z 7 [ 'name of 5th' ]
2017-01-06T18:51:03.863Z 21 [ 'name of 5th' ]
done

【讨论】:

    【解决方案2】:

    根据我对您在问题中提供的内容的理解。您的递归调用不在正确的位置。解决问题的一种方法是:

    function dependencies(array, callback){
      outerResult = async.map(array, function(item, outerNext){
        var innerResult = async.map(item.members, function(value, innerNext){
         //recursive_call_condition == true
         // for instance you want to check if value has an array further
         if(value.members.length) 
             dependencies(value.members, callback);
         else
             innerNext(null, innerResult);
        });
        outerNext(null, outerResult);
      }, function(err, finalResult){
         // `finalResult` is your result
         callback(finalResult)
      });
    }
    

    【讨论】:

      猜你喜欢
      • 2014-05-21
      • 2017-06-27
      • 2013-07-11
      • 2015-10-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多