Reputation: 435
async function wait(callback){
var awaited = await giveError();
return returner(awaited, callback)
}
function giveError(){throw new Error('oops')}
I was tasked to create the returner
function there, that would return a promise if there was no callback, and call the callback if it does exist
if returner
does nothing but return its first argument, it would return a promise, as desired
async function returner(awaited, callback){
console.log('triggering returner')
if(!callback){
return awaited
} else {
console.log('there is a callback')
}
}
wait().then(console.log).catch(err=>{
console.log('correct error catching here for async \n\n')
})
// prints 'correct error catching here for async'
the problem is that I have difficulty catching the error if there is a callback (with the assumption that awaited
is a promise)
wait(function(err, val){
console.log('callback error handling', err, val)
})
async function returner(awaited, callback){
console.log('triggering returner')
if(!callback){
return awaited
} else {
awaited
.then(val=>{
callback(null, val)
})
.catch(err=>{
callback(err)
})
}
}
// gives UnhandledPromiseRejectionWarning: Error: oops
I have questions:
why does 'triggering returner' never print?
is awaited
a promise? If not, is it possible at all to write the returner
function?
Upvotes: 0
Views: 171
Reputation: 138317
why does 'triggering returner' never print?
Because await
will behave like throw
if the promise it is waiting for rejects. Therefore the code terminates there and the error bubbles up, the return returner(..)
is never reached.
is awaited a promise?
No its the resolved value of the promise.
I would actually write a function that wraps the async function itself and takes the callback:
const withCallback = fn => (...args) => {
const last = args[args.length - 1];
if(typeof last === "function") {
return fn(...args.slice(0, -1))
.then(res => last(null, res))
.catch(last);
} else {
return fn(.. args);
}
};
That way you can write it as:
const wait = withCallback(async function wait(){
var awaited = await giveError();
return "result";
});
That allows you to do:
wait().then(/*...*/).catch(/*...*/)
// As well as
wait(function(error, result) { /*...*/ });
Upvotes: 1
Reputation: 26878
async
functions will always return a Promise
. If you want to configure your function's return type to vary based on the arguments, you will need to do so manually:
function foo(cb) {
if (typeof cb !== "function") {
return Promise.resolve("hello");
} else {
return cb("hello");
}
}
foo(v => console.log(v));
foo().then(v => console.log(v));
Upvotes: 0