I am completely new to Promises and async/await and just reading through tutorials etc., so I expect I may be missing something fundamental.
I've see this code pattern in several places, but I'm thinking maybe it should not be trusted:
async function myFunc() {
try {
var result = await doSomethingAsync();
console.log(result);
}
catch(error) {
console.error(error); // hmm
}
}
myFunc();
Consider the following scenario using the above pattern:
const doSomethingAsync = behaviour => new Promise((resolve, reject) => {
// use setTimeout to simulate e.g. an async webapi callback func
setTimeout(() => {
if(behaviour === "set resolve")
resolve("resolved");
if(behaviour === "set reject")
reject("rejected");
if(behaviour === "set after timeout error")
throw new Error("something went wrong after setTimeout returned");
}, 500);
if(behaviour === "set promise error")
throw new Error("something went wrong in promise");
});
async function myFunc(behaviour) {
try {
// wait for promise to complete
var result = await doSomethingAsync(behaviour);
console.log(result);
}
catch(error) {
console.error("caught:" + error); // will catch reject and promise error,
// but NOT after setTimeout error
}
}
myFunc("set promise error"); // caught:Error: something went wrong in promise
myFunc("set resolve"); // resolved
myFunc("set reject"); // caught:rejected
myFunc("set after timeout error"); // Uncaught Error: something went
// wrong after setTimeout returned
// UHOH!!
So the pattern seems a little misleading as it cannot catch the setTimeout error, whereas people tend to think of catch() as a catch-all.
Of course, changing the setTimeout to have an internal catch will solve the uncaught error problem:
const doSomethingAsync = behaviour => new Promise((resolve, reject) => {
// use setTimeout to simulate e.g. an async webapi call
setTimeout(() => {
try { // ...
}
catch(e) { reject("an error"); }
}, 500);
});
So, my questions are:
As I understand it, Promises are used as a replacement for callbacks, i.e. for wrapping async calls like setTimeout. So should there always be an internal try/catch -> reject pattern implemented inside a Promise? (So that the error can be gracefully handled by the caller). Do e.g. all node libraries work in this way? I can't see any way for the caller to deal with it by itself.
I find the pattern misleading, wouldn't the pattern be better like this?
async function myFunc(behaviour) {
try {
var result = await doSomethingAsync(behaviour);
.catch(e) { console.log("expected reject happened:" + e) };
}
catch(error) {
console.error("something totally unexpected happened:" + error);
}
}