2017-01-06 17 views
0

私は値を計算し、計算が別の関数へのコールバックで値を返す関数を持っています。function-nodejsでの非同期マップ、再帰、コールバックのコンボ

状況がかなり混ざり始めています。ここでは、2つのループと再帰のネストがあります。

エラーは次のとおりです。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); 
     } 
    }); 
} 

私はコメントで記述していますが、再帰呼び出しの前または後にinnerNextを記述する必要がありますか?この質問に加えて、私は2番目のマップの範囲の後にouterNextを呼び出す必要がありますか?

物事はかなり混乱しています。どのように私は解決するつもりですか?私はその文書を見ている。

**これは、最初のasync.mapの最後の場所ではありません。私はこの問題が、recursioneachasync.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は各ドキュメントを走査するためのもので、もう1つはその子配列を走査するためのものです。

私はそれが役立ちます:)

+0

をあなたが言及している再帰の周りに頭を抱えるのは苦労し、多分もっと文脈が助けになるでしょうか? – OliverRadini

+0

あなたのコードで再帰的なブレークはどこにありますか?依存関係()をもう一度呼び出さずに、次のコールバックを実行するような条件が必要であると言います。 –

+0

@OliverRadini大丈夫ですよ。更新をお待ちください。 – mmu36478

答えて

0

:として、あなたの問題を解決する1つの方法です。以下に実例を示します。 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 
0

をあなたは、あなたの質問に提供してきた何のための私の理解に基づいて願っています。再帰呼び出しが適切な場所にありません。あなたはSynJSを使用して、ループ、再帰とコールバックを混在させることができ

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) 
    }); 
} 
関連する問題