Both try's print Promise { <pending> }
and the second one has an Unhandled Promise Rejection Warning
. I've had success just using Promises with .then and .catch, but there's some stuff I'd like to code in more of a synchronous way using async/await. Should I be using Yield instead perhaps?
try {
var tokens = getNewTokens('refresh-token', 1)
console.log(tokens)
} catch (error) {
console.log(error.message)
}
try {
tokens = getNewTokens('no-such-refresh-token', 1)
console.log(tokens)
} catch (error) {
console.log(error.message)
}
function getRefreshToken (refreshToken, userId) {
return new Promise((resolve, reject) => {
if (refreshToken === 'refresh-token' && userId === 1) {
return resolve({
refreshToken: 'refresh-token',
accessToken: 'jwt'
})
} else {
const error = Error('Refresh token not found')
return reject(error)
}
})
}
async function getNewTokens (refreshToken, userId) {
if (!refreshToken || !userId) {
throw Error('Missing params')
}
try {
var result = await getRefreshToken(refreshToken, userId)
} catch (error) {
throw Error(error.message)
}
if (!result) {
throw Error('Something went bonk')
}
// Do stuff..
// get user from DB
// update refresh token with a new one
// make new jwt
return {
user: {
id: 1,
name: 'Jerry',
role: 'admin'
},
newRefreshToken: 'new-refresh-token',
newAccessToken: 'new-jwt'
}
}
Using async
and await
does not make your whole program asynchronous. It makes particular functions asynchronous. In the end, async
is syntactical sugar that makes writing promise code easier.
An async
function returns a Promise
. The code that calls the asynchronous function must treat it as a function that returns a promise. (The only exception is when the code that is calling the async
function is itself in an async
function, in which case it can be await
ed.)
So throwing an Error
gets translated into a Promise
rejection. You can't catch it in a try..catch
block for the simple reason that the try..catch
is over way before the error is thrown! (Again, the exception is when you're calling it from an async
function. If you are await
ing an asynchronous function, a try..catch
block will work. In this case the try..catch
block is treated as if it were adding a Promise#catch
function.)
You ultimately have to catch errors from an async
function using the normal Promise#catch
method or with the second argument to Promise#then
:
getNewTokens('no-such-refresh-token', 1)
.then(function(tokens) {
console.log(tokens);
}, function(error) {
console.log(error.message);
});
I would like to submit this as a reasonable and readable way to handle errors using async/await.
const value = await asyncFunction().catch(err => new Error(err))
if (value instanceof Error) return res.status(500).send('There was an error doing something')
By adding the .catch()
method, which returns an Error
, thus assigning it to the value
variable, we can be sure that some value will be present in our variable. The only additional line of code necessary is the if
statement to test if the value is an instance of Error
. If it was caught for any reason, it will definitely be an instanceof Error (our code makes sure of that), and our program can safely handle that scenario (in the above case we are returning 500 as a server response, thus preventing the program from executing any dangerous code as a result of the error in the asyncFunction).
I intentionally wrote this in 2 lines to highlight the fact that this can be written tersely and avoid the use of try
/catch
blocks, which many do not enjoy reading (myself being one).
If you're cool with reading try
/catch
blocks, congratulations. I just find it makes the code look janky. Oh well. ¯\_(ツ)_/¯
You cannot use await syntax outside of a function that is not declared with async or is a promise.
async function myAsyncFunction() {
// code
}
or
const myPromiseFunction = () => new Promise((resolve, reject) => {
// code
})
So ultimately, you have to use the old Promise way to consume a function declared as async
myAsyncFunction().then(() => console.log('here'));
because both are Promises.
Now to actually handle errors like you are used to in the then-catch way, you have to construct your async function like so...
async function getUser(username) {
return await db.users.get({ username });
}
then you can use this like a normal Promise outside of an async method like so...
getUser()
.then(user => console.log(user))
.catch(err => console.error(err));
or you guessed it, use it within an async function using await.
async function getJoffery() {
return await getUser('joffery');
}
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