I'm currently implementing a PDF viewer based on PDF.js and as part of that I learned about promise objects.
I also learned that runtime errors are not automatically shown in the debugging console:
PDFJS.getDocument(...).then(
function(pdfDocument){
alert(UndefinedVariable); // Not shown in console!
},
function(error){
console.log("Error occurred", error);
}
);
I haven't been able to find a pretty way to show runtime errors in the promise functions, other than adding .done()
as described in http://www.asyncdev.net/2013/07/promises-errors-and-express-js/ (which doesn't work for PDF.js) or adding .catch(function(error){ console.error(error); })
.
I know that I can break on exceptions from runtime errors in the debugger, but I also get breaks on other exceptions (in jQuery) by doing so, which means I have to step thorugh 5 jQuery exceptions on every page load, before I can even check if my own code contains runtime errors.
Is there any way to force the promise functions to log runtime errors like normal (without writing extra code for every function call)?
catch " around the executor automatically catches the error and turns it into rejected promise. This happens not only in the executor function, but in its handlers as well. If we throw inside a . then handler, that means a rejected promise, so the control jumps to the nearest error handler.
You cannot use try-catch statements to handle exceptions thrown asynchronously, as the function has "returned" before any exception is thrown. You should instead use the promise. then and promise. catch methods, which represent the asynchronous equivalent of the try-catch statement.
A promise is just an object with properties in Javascript. There's no magic to it. So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object.
We must always add a catch() , otherwise promises will silently fail. In this case, if thePromise is rejected, the execution jumps directly to the catch() method. You can add the catch() method in the middle of two then() methods, but you will not be able to break the chain when something bad happens.
The problem you're experiencing is that an exception in the then
callback does reject the promise returned by .then()
, instead of calling the error handler that you passed in. That will only trigger for errors in the promise on which you called .then()
. So you can chain your handlers:
PDFJS.getDocument(...).then(function(pdfDocument){
alert(UndefinedVariable); // Now shown in console!
}).then(null, function(error){
console.log("Error occurred", error);
});
Here, then(null, …)
could also be abbreviated by catch(…)
.
If there is no done
method that throws
on errors, you could implement it yourself like this by throw
ing in a setTimeout
.
Is there any way to force the promise functions to log runtime errors like normal (without writing extra code for every function call)?
No. That's just not how they were designed.
In the Promise implementation, there is a try ... catch which takes an error from the callbacks and turns it into an error returned by the Promise.
One thing you can do is change that try...catch to log the errors before invoking the failure of the promise.
https://github.com/mozilla/pdf.js/blob/master/src/shared/util.js#L936
} catch (ex) {
console.error(ex); // <--- add this line
nextStatus = STATUS_REJECTED;
nextValue = ex;
}
If native ECMAScript 6 promises are used instead, this trick probably won't work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With