admin管理员组

文章数量:1316616

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,
        })
    }
}

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,
        })
    }
}
Share Improve this question edited May 25, 2018 at 4:46 A. L asked May 25, 2018 at 3:37 A. LA. L 12.7k29 gold badges98 silver badges179 bronze badges 4
  • Are you handling the error, or ignoring it, leaving item_id as undefined? – Marcos Casagrande Commented May 25, 2018 at 4:22
  • @MarcosCasagrande I actually have an error handler inside the async function which is imported from another file – A. L Commented May 25, 2018 at 4:29
  • Can you post a little more of your code? So we get the full grasp of what you have, and how it can be improved. – Marcos Casagrande Commented May 25, 2018 at 4:30
  • @MarcosCasagrande updated, hopefully enough – A. L Commented May 25, 2018 at 4:35
Add a ment  | 

3 Answers 3

Reset to default 7

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.

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
});

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);
});

本文标签: javascriptdeclaring a const inside a trycatch block with awaitStack Overflow