Shamoon
Shamoon

Reputation: 43511

How can I properly use promises so my code isn't so nested?

This is my code. It continues to be very nested. I am using bluebird if that matters.

Promise.each BrowseNodes, (BrowseNode) ->
  amazonClient.browseNodeLookup
    browseNodeId: BrowseNode.browseNodeId
  .then (lookupResult) ->
    childNodes = lookupResult[0].Children[0].BrowseNode
    Promise.each childNodes, (childNode) ->
      amazonClient.browseNodeLookup
        browseNodeId: childNode.BrowseNodeId
        responseGroup: 'TopSellers'
      .then (results) ->
        items = results[0].TopSellers[0].TopSeller

Upvotes: 0

Views: 95

Answers (1)

Josh Beam
Josh Beam

Reputation: 19772

In general for getting rid of this waterfall effect, you can change something like this:

asyncService.doSomething()
.then(function(res) {
  asyncService.doSomethingElse(res)
  .then(function(secondRes) {
    asyncService.doAThirdThing(secondRes)
    .then(function(thirdRes) {
      // continue
    });
  });
});

to this:

asyncService.doSomething()
.then(function(res) {
  return res;
})
.then(function(res) {
  return asyncService.doSomethingElse(res);
})
.then(function(secondRes) {
  return asyncService.doAThirdThing(secondRes);
})
.then(function(thirdRes) {
  // etc.
});

This solution works because Promise methods return promises themselves.

This is a just an syntactic implementation detail, but the code does the same thing.

If you're using ES6 along with CoffeeScript, try using a library like co to leverage synchronous-looking async code (by using generators).

You can also use something like promise-waterfall, or see if there are any backfill libraries available for the upcoming ES7 async/await.

edit

To handle Promise.each:

.then(function() {
  return Promise.each(/* do stuff */);
})
.then(function(result) {
  // do stuff
});

Upvotes: 1

Related Questions