问题
I have a function doSomething()
that returns a promise chain, utilizing the Q framework. The contents are similar to something like:
loadDataSet : function (params) {
return Q.fcall(function() {
//Do Something
})
.then(function(){
//Do Something Else
throw New Error('unexpected error');
});
}
The calling code goes something like:
var promise = loadDataSet(args);
I want to figure out whether that error was thrown. Notice, in the loadDataSet
function implementation, I did not utilize the .done()
function.
So far, I have code that looks like this and have been unsuccessful in capturing the error and handling it appropriately (here, the code is modified, slightly from above):
try {
loadDataSet(args)
.catch(function(error) {
return error
})
.done();
}....
The goal is to handle the error from a try-catch block. What am I missing?
回答1:
Well, this is going to a be a bummer.
You can't
While a lot of promise libraries let you do this and will report unhandled rejections for you - in Q you have no methods to automatically detect these failures.
You have to Use .done
or change a promise library. Heck, even native promises are going to be able to do this in a few days.
Q specific solution:
In Q your only realistic option is to use .done
, unlike then
done is not throw safe and you can throw exceptions from there and they won't be suppressed - this requires you to remember to always terminate chains with done
but it works:
myObj.loadDataSet(handleSuccess, handleError).done(); // will throw on rejection
Personally until Q fixes this and other issues I cannot recommend using it to anyone.
Modern libraries and native promises
I've written a specification based on work by Domenic and Petka for promise libraries to be able to report errors globally and hook to them. Several libraries already implement this including bluebird and when. Domenic is working on a parallel specification for web browsers.
Currently supported or are going to be supported in the next few weeks are: bluebird, when, es6-promise, rsvp and native promises in io.
// log any unhandled promise rejections
process.on('unhandledRejection', function(reason, p){
console.log("Possibly Unhandled Rejection at: Promise ", p, " reason: ", reason);
// application specific logging here
});
As for browsers, something like:
window.addEventListener("unhandledrejection", function(e) {
var reason = e.detail.reason;
var promise = e.detail.promise;
console.log("Unhandled rejection", promise, reason);
});
This protocol is less supported but there are plans to include it in native promises. Currently Firefox native promises will report unhandled rejections and Chrome's will attempt too - but there are no browser hooks for it yet (it's coming though).
Note that teams are working on very interesting tooling. After a discussion with Paul Irish I'm convinced great things are going to come our way in terms of tooling for debugging promises in browsers that will make native promises almost as debuggable as bluebird promises (which is awesome!).
回答2:
You can't throw exceptions inside then
as no one will able to catch it. Instead, create a new Q.defer
and call reject on it whenever there's an error
loadDataSet : function (params) {
var deferred = Q.defer()
Q.fcall(function() {
//Do Something
}).then(function(){
//Do Something Else
deferred.reject('error message')
}, deferred.reject)
return deferred.promise
}
then use it like this
loadDataSet().then(function (data) {
//ok, got data
}).catch(function (err) {
//error!
})
来源:https://stackoverflow.com/questions/28417359/function-returns-a-promise-check-errors