Reputation: 12649
So I currently have this:
var item_id
try {
item_id =
await
(async function () {
// code
})();
} catch (error) {
}
But I'd much prefer having item_id
as a const. What's the best way to assign the await value to a const, given that node requires me to handle promise rejection
e.g. Errors:
[0] (node:77118) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: details[Symbol.iterator] is not a function
[0] (node:77118) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Async code
await
(async function () {
const query = `
INSERT INTO item (list_id)
SELECT
?
FROM
list
WHERE
id = ?
AND
user_id = ?
LIMIT 1;
`
const results =
await
doQuery({
inputs: [
list_id,
list_id,
req.session.user.id
// 10
],
query,
error_message: "item create mysql error"
})
return results.insertId === 0 ? false : results.insertId
})();
doQuery
function doQuery({ query, inputs, error_message, res = null }) {
return (
new Promise(function (resolve, reject) {
db.query(query, inputs, function (err, results, fields) {
if (err) {
console.trace(chalk.green(db.sql))
console.log()
handleError({ error: err, error_message, res })
reject(err)
return
}
resolve(results)
})
})
)
}
handleError
function handleError({ error, message, res }) {
console.trace(chalk.yellow(message))
console.trace(chalk.red(error))
console.log()
if (res) {
res.send({
error: true,
success: false,
})
}
}
Upvotes: 6
Views: 2785
Reputation:
This is a well-known problem which has been discussed elsewhere.
Your options include:
Just declaring item_id
with let
at the outer level as you have done. Nothing wrong with that.
Depending on what you want to do with item_id
, do that inside the try/catch
block, allowing you to declare const item_id;
inside the try
.
Make sure you really need a try/catch
. Remember that any error thrown inside an async
function will automatically translate into a rejection of the promise being returned by the function. You don't have to (and in may cases don't want to) catch it; instead, handle the error at a higher level. Node "requiring you to handle promise rejection" does not mean you have to handle it right here where it occurs; you can handle it at any higher level. Remember that catch
'ing the error here will put the async function back on the "happy path" (unless you re-throw) and the calling function will have no way of knowing there was an error.
In some cases, your code will be more readable if you go back to using promises, and .catch()
, as in
const item_id_promise = async function () {}();
item_id_promise.catch(...);
or possibly even just
return (async function() { }()).catch(...)
But actually your question has nothing to do with await
, async
, or promises. It's just about block-scoping of variables inside blocks, in this case a try
block. Yes, const
and let
are block-scoped, and therefor are scoped to the try
clause. So like anything else, if you want to use them outside the try
block, you have to declare them outside the try
block. Or, if you really don't want to declare them outside the try
block, you can't use them outside the try
block, so you have to arrange to use them only inside it, if that's possible.
Upvotes: 7
Reputation: 27224
Following @torazaburo's suggestion:
const item_id = async function () {
// code
return 1337; // return your expected item id
}();
item_id.catch(function (e) {
console.error(e);
});
Upvotes: 1
Reputation: 13
You could define your function in another scope using the power of Promises such as:
async function foo(bar) {
return new Promise((resolve, reject) => {
if(bar === 'baz') {
resolve(bar); // Resolve this promise
} else {
reject(); // Reject this promise
}
});
}
foo('baz').then(baz => {
// Do something with 'baz', the result of the resolved promise
}).catch(error => {
// The promise is rejected, process an error here
});
Upvotes: 1