【问题标题】:async and await and promise in regards to catching errors关于捕获错误的异步、等待和承诺
【发布时间】:2018-07-19 12:58:49
【问题描述】:

我有一个关于在异步中捕获用户错误并等待的问题。

假设我有一条只为单个用户获取的路线。

routes.js

routes.get('/getuserbyid/:id', (req, res) => {

    const id = req.params.id;

    accountController.getById(id)
        .then((result) => {
            res.json({
                confirmation: 'success',
                result: result
            });
        })
        .catch((error) => {
            res.json({
                confirmation: 'failure',
                error: error
            });
        });
});

我有一个获取请求的控制器。 accountController.js

export const getById = async (id) => {

        try {
            const user = await users.findOne({ where: {
                    id: id
                }});

            if (user === null) {
                return 'User does not exist';
            }
            return user;
        } catch (error) {
            return error;
        }
}

所以无论发生什么,我都会得到一个空记录或一条记录。它仍然是成功的。 在 Promise 中,我可以拒绝 null,因此它会显示在路由的 catch 块中。现在有了异步和等待。如何在错误块中实现同样的效果?

export const getById = (id) => {

    return new Promise((resolve, reject) => {

        users.findOne({ where: {
            id: id
        }})
            .then((result) => {

                if (result === null) {
                    reject('User does not exit');
                }
                resolve(result);
            })
            .catch((error) => {
                reject(error);
            });
    });

}

【问题讨论】:

  • 你会throw null;
  • 我可以在这里看到几个问题。首先,严格测试(user === null) 可能会遗漏一些错误情况,例如undefined。其次,try/catch 是不必要的并且可以消失。如果user 是一个有效的用户对象之外的任何东西,只需立即抛出一个错误。它将由您上面的.catch() 回调处理。

标签: javascript promise async-await ecmascript-2017


【解决方案1】:

首先,避免使用 Promise 反模式。您有一个返回 Promise 的函数,无需将其包装在 new Promise() 中。

那么你的函数可能如下所示:

export const getById = (id) => {
  return users.findOne({ where: { id } })
    .then((user) => {
      if (user === null)
        throw 'User does not exit';

      return user;
    });
}

这个的异步/等待版本是

export const getById = async (id) => {
  const user = await users.findOne({ where: { id } });

  if(user === null)
    throw 'User does not exist';

  return user;
}

【讨论】:

  • 谢谢!这正是我所需要的。
【解决方案2】:

async 函数始终返回 Promise

async 函数中使用throw 构造会拒绝返回的Promise

考虑

function getValue() {
  return Promise.reject(null);
}

getValue().catch(e => {
  console.log('An raised by `getValue` was caught by a using the `.catch` method');
  console.log(e);
});


(async function main() {
  try {
    await getValue();
  } catch (e) {
    console.log('An raised by `getValue` was caught by a catch block');
    console.log(e);
  }
}());

async function getValue() {
  throw null;
}

getValue().catch(e => {
  console.log('An raised by `getValue` was caught by a using the `.catch` method');
  console.log(e);
}); 

(async function main() {
  try {
    await getValue();
  } catch (e) {
    console.log('An raised by `getValue` was caught by a catch block');
    console.log(e);
  }
}());

异步方法中的try 块处理同步异步错误。

考虑

function throws() {
  throw Error('synchronous failure');
}


async function rejects() {
  throw Error('asynchronous failure');
}

(async function main() {
  try {
    throws();
  } catch (e) {
    console.log('asynchronously handled', e.message);

  }

  try {
    await rejects();
  } catch (e) {
    console.log('asynchronously handled', e.message);
  }
}());

要记住的关键点是,如果您忘记await 拒绝它们的承诺,则不会捕获异步错误。这类似于忘记.then 内部的return.catch 回调

【讨论】:

    【解决方案3】:

    如果你的值为空,你可以抛出异常。

    export const getById = async (id) => {
            const user = await users.findOne({ where: {
                    id: id
                }});
    
            if (!user) {
                throw Error('User does not exist..');
            }
            return user;        
    }
    

    【讨论】:

    • 这是行不通的,因为你正处于 try/catch 的中间,抛出的错误将被捕获,然后从异步函数返回,这不是 promises 应该的方式工作。只需完全删除 try/catch 包装器,效果会更好。
    猜你喜欢
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    相关资源
    最近更新 更多