NodeJS Promise (Q) - How to get a value if the promise fails?
javascript, node.js, promise, q
Solution
I recommend this approach:
return makeImage().then(function (path) {
return doSomeCoolThings(path)
.finally(function () {
return removeImage(path);
});
});
Assuming you trust makeImage, removeImage, and doSomeCoolThings to return Q promises and never throw. Otherwise, there’s always `Q.fcall` which eliminates these concerns.
If you wish to retain the image in the success case, and only delete it if there’s a failure, rethrowing the error:
return Q.fcall(makeImage).then(function (path) {
return Q.fcall(doSomeCoolThings, path)
.catch(function (error) {
return Q.fcall(removeImage, path)
.thenReject(error);
});
});
Also, instead of:
var deferred = Q.defer();
deferred.resolve(x);
return deferred.promise;
You can:
return Q.resolve(x);
Problem
I´m starting to use promises in my NodeJS projects and I run into a problem. After I read the Promises/A+ spec and googling a lot I didn´t find a nice solution for the case that I need to access a value which gets produced in a promise chain. In my example I want to check when an error occurs if the image was created and if so, I want to delete it. Code: ``` var Q = require('Q'); var fs = require('fs'); // This produces the imgPath function makeImage() { var deferred = Q.defer(); deferred.resolve("path/to/image"); return deferred.promise; } function watermark(imgPath) { var deferred = Q.defer(); deferred.resolve(imgPath); return deferred.promise; } // This function fails function doSomeCoolThings(imgPath) { var deferred = Q.defer(); deferred.reject(new Error("System is exploded")); return deferred.promise; } var fileExists = Q.denodeify(fs.readFile); var deleteFile = Q.denodeify(fs.unlink); // How do I get the imgPath here? function deleteImageIfPresent(err) { return Q.fcall(function () { return imgPath !== undefined; }) .then(fileExists) .then(deleteFile); } var iKnowThatSolution; makeImage() // Thats not what I want //.then(function(imgPath) { // iKnowThatSolution = imgPath; //}) .then(watermark) .then(doSomeCoolThings) .fail(deleteImageIfPresent); ```