0

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
Shamoon
  • 41,293
  • 91
  • 306
  • 570
  • You don't have to inline functions. Why don't you define them beforehand and put into variables? E.g. `onError = ...`, `onBrowseNodeSuccess = ...` – Sulthan Nov 27 '15 at 22:46
  • You can use chaining instead of nesting checkout http://stackoverflow.com/questions/26305267/best-way-to-handle-nested-promises-bluebird – pwilmot Nov 27 '15 at 22:48
  • related, if not duplicate: [How to optimize this Node.js + q code to prevent callback hell?](http://stackoverflow.com/q/26383057/1048572). You cannot avoid nesting completely when you want to loop. And there's nothing wrong with that. – Bergi Nov 28 '15 at 23:26

1 Answers1

1

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
});
Josh Beam
  • 19,292
  • 3
  • 45
  • 68