Async db使用递归调用

时间:2015-04-14 09:31:39

标签: javascript node.js asynchronous recursion

我需要以递归方式下载链表数据库树

item 1-> item 2
      -> item 3 -> item 4
      -> item 5 -> item 6 -> item 7
      -> item 8

我的伪代码是

var getItems = function(itemid) {
    db.getitem(itemid, function(item) {

    item.items.forEach(function(subitem) {
        getItems(subitem.id)
    })
})

getItems(1)

但是,db.getItem是一个异步函数

我想将与图表相同结构的JS对象返回给顶级调用者

实现这一目标的最佳方法是什么?我不知道前面的结构(即不知道每个项目的项目数量,或者树中任何分支的深度)所以我不知道我需要处理的项目数量

我尝试了异步库的各种方法,但似乎都没有处理递归

1 个答案:

答案 0 :(得分:3)

这是强大的并发原语发光的地方。

承诺让你轻松地做到这一点:

// with bluebird this is var getItem = Promise.promisify(db.getitem);
var getItem = function(itemid){
     return new Promise(function(resolve, reject){
        db.getitem(itemid, function(err, data){
            if(err) reject(err);
            else resolve(data);
        });
     });
};

可以让你这样做:

var getItems = function(itemid) {
    return getItem(itemid).then(function(item){ // get the first
       return Promise.all(item.items.forEach(function(subItem){
           return getItems(subitem.id);
       });
    }).then(function(subItems){
        var obj = {};
        obj[itemid] = subItems; // set the reference to subItems
        return obj; // return an object containing the relationship
    });
};


getItems(1).then(function(obj){
   // obj now contains the map as you describe in your problem description
});

以下是async的外观:

var getItems = function(itemid, callback){
   db.getitem(itemid, function(err, item){
       if(err) return callback(err, null);
       async.map(item.items, function(subitem, cb){
           getItems(subitem.id, cb);
       }, function(err, results){
           if(err) return callback(err, null);
           var obj = {};
           obj[itemid] = result;
           return callback(null, obj);
       });
   });
};

它非常接近,但我认为它比承诺版本要好得多。