A. L
A. L

Reputation: 12649

declaring a const inside a try/catch block with await

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

Answers (3)

user9315861
user9315861

Reputation:

This is a well-known problem which has been discussed elsewhere.

Your options include:

  1. Just declaring item_id with let at the outer level as you have done. Nothing wrong with that.

  2. 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.

  3. 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.

  4. 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

gotnull
gotnull

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

Diego Villalobos
Diego Villalobos

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

Related Questions