Using Q / promises against callbacks

I use the Q library in nodejs and have not worked too much with promises in the past, but I have semi-complex logic that requires a lot of nesting, and the thought of Q would be a good solution, however I find it seems almost the same as just a callback hell ".

Basically I say 5 methods, all of which require data from the previous or one of the previous. Here is an example:

We start with some binary data that has the sha1 hash file generated from the binary.

var data = {
    hash : "XXX"
  , binary: ''
}

First we want to see if we have this using this method:

findItemByHash(hash)

If we don’t have it, we need to save it using:

saveItem(hash)

, . , , , :

getItemHierarchy(item_id), item_id, saveItem

"" :

saveUserHierarchy(hierarchy)

, , . , . :

, :

getUserItemByItemId(item_id) - item_id findItemByHash

, .

:

getItemHierarchy(item_id)

saveUserHierarchy(hierarchy)

, , , . . , . , - , .

Q - :

findItemByHash(hash).then(function(res) {

    if (!res) {

     return saveItem(hash).then(function(item) {
        return getItemHierarchy(item.id).then(function(hierarchy) {
            return saveUserHierarchy(hierarchy);
        });
     })

    } else {

      return getUserItemByItemId(res.id).then(function(user_item) {

         if (user_item) {
            return user_item;
         } 

        return getItemHierarchy(res.id).then(function(hierarchy) {
            return saveUserHierarchy(hierarchy);
        });

      });

    }
})
//I think this will only handle the reject for findItemByHash?
.fail(function(err) {
   console.log(err);
})
.done();

, , . Q?

!

+4
1

, promises, , . , - promises , , . fail, , .

- . - :

function awesomeFunction() {
    var fooPromise = getFoo().then(function() {
        return 'foo';
    }).fail(function(reason) {
        // handle the error HERE, return the string 'bar'
        return 'bar';
    });

    return fooPromise;
}

awesomeFunction().then(function(result) {
    // `result` will either be "foo" or "bar" depending on if the `getFoo()`
    // call was successful or not inside of `awesomeFunction()`
})
.fail(function(reason) {
    // This will never be called even if the `getFoo()` function fails
    // because we've handled it above.
});

"return hell" - , .then :

doThis().then(function(foo) {
    return thenThis(foo.id).then(function(bar) {
        // `thenThat()` doesn't need to know anything about the variable
        // `foo` - it only cares about `bar` meaning we can unnest it.
        return thenThat(bar.id);
    });
});

// same as the above
doThis().then(function(foo) {
    return thenThis(foo.id);
}).then(function(bar) {
    return thenThat(bar.id);
});

, , , :

function getItemHierarchyAndSave(item) {
    return getItemHierarchy(item.id).then(function(hierarchy) {
        return saveUserHierarchy(hierarchy);
    });
}

findItemByHash(hash).then(function(resItem) {
    if (!resItem) {
        return saveItem(hash).then(function(savedItem) {
            return getItemHierarchyAndSave(savedItem);
        });
    }

    return getUserItemByItemId(resItem.id).then(function(userItem) {
        return userItem || getItemHierarchyAndSave(resItem);
    });
})
.fail(function(err) { console.log(err); })
.done();

: Q promises, perfer when promises , , .

+4

All Articles