繁体   English   中英

async /等待正确的错误处理

[英]async / await proper error handling

假设我们有一个在用户登录(express,node)上运行的动作。 这是使用大量回调编写的代码:

checkIfEmailAndPasswordAreSet(email, password, (error, response) => {
  if (error) return errorResponse(403, 'validation error', error)
  findUserByEmail(email, (error, user) => {
    if (error) return errorResponse(500, 'db error', error)
    if (!user) return errorResponse(403, 'user not found')
    checkUserPassword(user, password, (error, result) => {
      if (error) return errorResponse(500, 'bcrypt error', error)
      if (!result) return errorResponse(403, 'incorrect password')
      updateUserLastLoggedIn(user, (error, response) => {
        if (error) return errorResponse(500, 'db error', error)      
        generateSessionToken(user, (error, token) => {
          if (error) return errorResponse(500, 'jwt error', error)
          return successResponse(user, token)
        })
      })
    })
  })
})

我想用async / await重写这段代码,避免回调地狱。 怎么做?

第一次尝试可能看起来像这样:

try {
  await checkIfEmailAndPasswordAreSet(email, password)
  const user = await findUserByEmail(email)
  if (!user) throw new Error('user not found')
  const result = await checkUserPassword(user, password)
  if (!result) throw new Error('incorrect password')
  await updateUserLastLoggedIn(user)
  const token = await generateSessionToken(user)
  return successResponse(user, token)
} catch (e) {
  // How to handle the error here?
}

我想保持正确的错误处理,即如果在checkUserPassword方法中抛出错误,我希望响应包含有关此的信息。 我应该在catch方法中写什么?

例如,我可以将每条指令包装到它自己的try / catch块中,如下所示:

try {

  let user, result

  try {
    await checkIfEmailAndPasswordAreSet(email, password)
  } catch (error) {
    throw new Error('This error was thrown in checkIfEmailAndPasswordAreSet')
  }

  try {
    user = await findUserByEmail(email)
  } catch (error) {
    throw new Error('This error was thrown in findUserByEmail')
  }

  if (!user) throw new Error('user not found')

  ...
} catch (error) {
  return errorResponse(error)
}

但是这段代码..可能那不是回调地狱,但我会称之为try / catch hell。 它使用原始旧式代码与回调相比至少需要2倍的行数。 如何将其重写为更短并利用async / await?

使用try / catch无法轻松处理个别错误

我可能会编写一些辅助函数来简化错误抛出:

function error(code, msg) {
    return e => {
        e.status = code;
        e.details = msg;
        throw e;
    };
}
function ifEmpty(fn) {
    return o => o || fn(new Error("empty"));
}

然后使用标准的promise方法:

try {
    await checkIfEmailAndPasswordAreSet(email, password)
        .catch(error(403, 'validation error'));
    const user = await findUserByEmail(email)
        .then(ifEmpty(error(403, 'user not found')), error(500, 'db error', error));
    await checkUserPassword(user, password)
        .then(ifEmpty(error(403, 'incorrect password')), error(500, 'bcrypt error'));
    await updateUserLastLoggedIn(user)
        .catch(error(500, 'db error'));
    const token = generateSessionToken(user)
        .catch(error(500, 'jwt error'));
    return successResponse(user, token);
} catch(err) {
    errorResponse(err.status, err.details, err);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM