This is obviously a SSCCE. I have the following (jsFiddle here):
<html>
<body>
<input id='file-dlg' type='file'/>
<br/>
<button id='submit' type='button'>submit</button>
<script>
document.getElementById('file-dlg').addEventListener('change', storeAPromise);
var p;
function storeAPromise() {
p = new Promise(function executor(resolve, reject) {
try {
throw new Error('snafu');
} catch(e) {
reject(e);
}
});
};
document.getElementById('submit').onclick = function() {
p.then(function() {}, function reject(e) {
console.error('some problem happenned', e);
});
};
</script>
</body>
</html>
When the user is using the file dialog to select a file, I expect nothing at all to be printed on the console as the Error
is caught and the promise's reject
function is called. In contrast, I am expecting the error to appear on the console with the description "some error happened" only when I click the "submit" button.
Yet, this is not what I observe. As soon as the user selects a file with the dialog I see on the console:
Uncaught (in promise) Error: snafu(…)
When the user presses the "submit" button I do see the expected log line "some problem happened" but I don't understand why I also see the earlier "Uncaught (in promise)" log line when the user selects a file with the file dialog. I also don't see why the error is described as "Uncaught" given that I catch (unconditionally) all exceptions and simple invoke the reject
function.
What does that log "Uncaught (in promise)" mean? It means that there was an error in one of our promises, but we did not write any code in order to handle that error and try to catch it.
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.
allSettled() always resolves, even if some promises passed to it reject. It resolves with an array of outcomes for each promise. You can use Promise. all() instead, which will resolve when all passed promises resolve or reject when any passed promise rejects.
If an error condition arises inside a promise, you “reject” the promise by calling the reject() function with an error. To handle a promise rejection, you pass a callback to the catch() function. This is a simple example, so catching the rejection is trivial.
It's not an uncaught exception, it's an uncaught rejection. Promises should not be left dangling in the rejected state with no error callback attached - that's why the console is warning you about this. You can also handle these cases in your application with the unhandledrejection
event.
If you want to handle the error later (install the handler when the user clicks the button, which might be never!), you still will need to immediately install an empty callback (that explicitly ignores the error) to suppress the warning.
var p = Promise.resolve();
document.getElementById('file-dlg').addEventListener('change', function createPromise() {
p = new Promise(function executor(resolve, reject) {
throw new Error('snafu');
});
p.catch(e => {/* ignore for now */});
});
document.getElementById('submit').addEventListener('click', function addErrorHandler() {
p.catch(function onReject(e) {
console.error('some problem happened', e);
});
});
Notice that you don't need that try
/catch
- the promise constructor will catch all exceptions from the executor by default already.
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