Async db calls using recursion

≯℡__Kan透↙ 提交于 2021-02-11 07:33:27

问题


I have a need to recursively descend a linked list database tree

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

my pseudo code is

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

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

getItems(1)

however, db.getItem is an asynchronous function

I would like to return a JS object in the same structure as the diagram to the top-level caller

what is the best way of achieving this ? I don't know the structure up front (i.e. no idea on the number of items per item, or the depth of any branch in the tree) so I have no idea on the number of items I need to process

I have tried various methods of the async library, but none seem to deal with recursion


回答1:


This is where strong concurrency primitives shine.

Promises let you do this very easily:

// 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);
        });
     });
};

Which would let you do:

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
});

Here is how it would look with 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);
       });
   });
};

It gets pretty close but I think it's a lot less nice than the promise version.



来源:https://stackoverflow.com/questions/29623847/async-db-calls-using-recursion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!