Removing nested promises
Solution 1:
From every then
callback, you will need to return the new promise:
exports.viewFile = function(req, res) {
var fileId = req.params.id;
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequest('documents', {url: response.request.href}, 'POST');
})
.then(function(response) {
return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST');
})
.then(function(response) {
console.log(response);
});
};
The promise that is returned by the .then()
call will then resolve with the value from the "inner" promise, so that you easily can chain them.
Generic pattern:
somePromise.then(function(r1) {
return nextPromise.then(function(r2) {
return anyValue;
});
}) // resolves with anyValue
||
\||/
\/
somePromise.then(function(r1) {
return nextPromise;
}).then(function(r2) {
return anyValue;
}) // resolves with anyValue as well
Solution 2:
Promise.prototype.then
is designed to return another promise, so that you can chain them.
The handler function passed to .then()
can return a normal value, like a number or string or object, and this value will get passed on to the next handler of .then()
.
One option is to have boxViewerRequestSync
be a synchronous function that returns a response
object:
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequestSync('documents', {url: response.request.href}, 'POST')
})
.then(function(response) { // this `response` is returned by `boxViewerRequestSync`
return boxViewerRequestSync('sessions', {document_id: response.body.id}, 'POST')
})
.then(function(response) {
console.log(response);
})
But of course your boxViewerRequest
is asynchronous and returns a promise instead. In that case, the handler function passed to .then()
could also return a completely unrelated Promise
. This new promise is executed synchronously, and once it is resolved/rejected, its result is passed on to the next handler.
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequest('documents', {url: response.request.href}, 'POST')
})
.then(function(response) { // this `response` is the result of resolving the promise returned by `boxViewerRequest`
return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST')
})
.then(function(response) {
console.log(response);
})
Keeping track of all the promises is confusing, but the bottom line is this: Promise.prototype.then
will always return a Promise object, but the handler function passed to Promise.prototype.then
can return anything, even undefined, or even another Promise. Then that value, or the value of the resolved Promise, is passed to the next handler function.