2017-05-06 69 views
1

我有一個簡單的樹,其中包含的id是Mongo集合的鍵。我正在使用名爲treewalker的節點庫。當我遍歷樹的每個節點時,我試圖查找名稱(使用貓鼬)並簡單地將它附加到當前節點。如果我沒有做回調來查找節點名稱,只是使用一些固定值,我會得到我期待的值。讓我來說明代碼:在樹形漫步完成後執行回調函數

這裏是我的樹:

{ 
    "categoryTree": [ 
    { 
     "categoryId": "1", 
     "children": [ 
     { 
      "categoryId": "2", 
      "children": [ 
      { 
       "categoryId": "3", 
       "children": [] 
      }, 
      { 
       "categoryId": "4", 
       "children": [] 
      } 
      ] 
     }, 
     { 
      "categoryId": "5", 
      "children": [] 
     }, 
     { 
      "categoryId": "6", 
      "children": [] 
     } 
     ] 
    }, 
    { 
     "categoryId": "7", 
     "children": [ 
     { 
      "categoryId": "8", 
      "children": [] 
     } 
     ] 
    } 
    ] 
} 

這裏是代碼,做什麼,我想:只要我扔

catTree.categoryTree.forEach(function(node){ 
    var counter = 0; 
    tree.walkTree(node, 'children', function(obj){ 
     obj.name = counter++; 
    }); 
}); 
//This tree has the names (as the counter above) in it as I expect 
console.log(JSON.stringify(catTree)); 

然而,在貓鼬回調獲取類別名稱,打印的類別樹不再具有名稱。

catTree.categoryTree.forEach(function(node){ 
    tree.walkTree(node, 'children', function(obj){ 
     //Cat is a mongoose model defined elsewhere 
     Cat.findById(obj.categoryId, {_id:0,name:1}).exec(function(err, value){ 
      obj.name = value.name; 
     }); 
    }); 
}); 
//This tree has NO names :(
console.log(JSON.stringify(catTree)); 

我知道這是一個時間問題,但我無法弄清楚如何解決它。我見過幾個SO條款like this one,建議跟蹤回調,並在所有被調用後繼續。我無法弄清楚如何將這種模式應用到我的案例中,因爲我正在行走一棵樹,而不僅僅是迭代一個扁平列表。我開始認爲我的問題可能是我正在使用樹行程庫,而不是在訪問每個節點後用回調函數編寫我自己的算法。

我真的很感謝你的幫忙!

+0

看看async.js – Alex

回答

2

您的數據庫調用是異步的。這意味着他們將在未來完成一段時間,在迭代完成之後很久。如果你的數據庫可以處理查詢的一整棵樹在它被扔在一次(運行基本並行所有這些查詢),那麼你可以做這樣簡單的東西:

let cntr = 0; 
catTree.categoryTree.forEach(function(node){ 
    tree.walkTree(node, 'children', function(obj){ 
     //Cat is a mongoose model defined elsewhere 
     ++cntr; 
     Cat.findById(obj.categoryId, {_id:0,name:1}).exec(function(err, value){ 
      --cntr; 
      if (!err) { 
       obj.name = value.name; 
      } 
      // see if all requests are done 
      if (cntr === 0) { 
       console.log(JSON.stringify(catTree)); 
      } 
     }); 
    }); 
}); 

你想隨時協調不止一個異步操作,通常使用承諾是有意義的(因爲這正是它們的目的),並且貓鼬有內置的查詢承諾。在這裏,您將每個查詢的承諾收集到一個數組中,然後Promise.all()告訴您何時完成。

let promises = []; 
catTree.categoryTree.forEach(function(node){ 
    tree.walkTree(node, 'children', function(obj){ 
     //Cat is a mongoose model defined elsewhere 
     let p = Cat.findById(obj.categoryId, {_id:0,name:1}).exec().then(function(value) { 
      obj.name = value.name; 
     }); 
     promises.push(p); 
    }); 
}); 

Promise.all(promises).then(function() { 
    console.log(JSON.stringify(catTree)); 
}).catch(function(err) { 
    // error 
    console.log(err); 
}); 
+0

這太棒了!感謝答覆和承諾解釋。如果我可以給你買一瓶啤酒,我會的。 – tobyb

相關問題