Reputation: 8237
How can I avoid nesting-hell with a chain of service calls in Node.js, where I'd like to throw a given error and exit the entire chain in certain instances? Here's an example of the chain:
res.send(404)
; if load succeeds, go to the next then()
.500
just for the sake of this problem)If API call succeeds, render the page.
SomeMongooseModel.findOne({id:123}).exec()
.then(function(response)
{
// If group is empty, would like to res.send(404) and resolve the
// promise immediately.
})
.then(function(response)
{
// Hit 3rd party API to retrieve data. If there's an issue, return
// response code of 500 and resolve promise immediately.
// Assuming the API call was a success, build out an object and render
// the page like so:
res.render('some.template', {data: some_data});
});
I think this is a decent example of what I'm trying to achieve, but what if we had even more async calls to handle? How can we exit the chain immediately? I've done a bit of searching and I know that I have a lot more to learn, but I'm not finding the ability to simply exit the chains immediately.
Upvotes: 1
Views: 1084
Reputation: 37147
When faced with this I normally separate everything into functions, which I then pass a reference into the promise. With good names it also benefits the reading:
function resolveNotFoundIfGroupEmptyOrForwardResponse( response ) { res.send(404) }
function hit3rdPartyApiBasedOnResponse( response ) {
// throw exception if there is an issue. next step will run the failure state
}
function render500() { ... }
function renderTemplateWithData( some_data ) {
res.render('some.template', {data: some_data});
}
SomeMongooseModel.findOne({id:123}).exec()
.then( resolveNotFoundIfGroupEmptyOrForwardResponse )
.then( hit3rdPartyApiBasedOnResponse )
.then( renderTemplateWithData, render500 )
.done();
If the function requires an input param that is not comming from the promise chain, then I normally do a function that returns a function.
function doStuffWithParamsCommingFromTwoSides( main_input ) {
return function( promise_input ) {
...
}
}
then( doStuffWithParamsCommingFromTwoSides( "foobar" ) )
Following Promises/A+ specification, the then
steps look like this:
promise.then(onFulfilled, onRejected, onProgress)
Whenever an exception is thrown the next step will run the onRejected
. Eventually bubbling up to the done
which can also be used to catch the exception bubble.
promise.done(onFulfilled, onRejected, onProgress)
Upvotes: 1