异步等待使用和错误处理问题

时间:2017-01-23 18:19:02

标签: javascript node.js async-await

两者都尝试打印Promise { <pending> },第二个打印Unhandled Promise Rejection Warning。我在使用.then和.catch的Promise方面取得了成功,但是我想要使用async / await以更多的同步方式编写代码。我可能会使用Yield吗?

try {
  var tokens = getNewTokens('refresh-token', 1)
  console.log(tokens)
} catch (error) {
  console.log(error.message)
}

try {
  tokens = getNewTokens('no-such-refresh-token', 1)
  console.log(tokens)
} catch (error) {
  console.log(error.message)
}

function getRefreshToken (refreshToken, userId) {
  return new Promise((resolve, reject) => {
    if (refreshToken === 'refresh-token' && userId === 1) {
      return resolve({
        refreshToken: 'refresh-token',
        accessToken: 'jwt'
      })
    } else {
      const error = Error('Refresh token not found')
      return reject(error)
    }
  })
}

async function getNewTokens (refreshToken, userId) {
  if (!refreshToken || !userId) {
    throw Error('Missing params')
  }
  try {
    var result = await getRefreshToken(refreshToken, userId)
  } catch (error) {
    throw Error(error.message)
  }
  if (!result) {
    throw Error('Something went bonk')
  }
  // Do stuff..
  // get user from DB
  // update refresh token with a new one
  // make new jwt
  return {
    user: {
      id: 1,
      name: 'Jerry',
      role: 'admin'
    },
    newRefreshToken: 'new-refresh-token',
    newAccessToken: 'new-jwt'
  }
}

3 个答案:

答案 0 :(得分:16)

使用asyncawait不会使整个程序异步。它使特定函数异步。最后,async是语法糖,使编写承诺代码变得更容易。

async函数返回Promise。调用异步函数的代码必须将其视为返回promise的函数。 (唯一的例外是调用async函数的代码本身位于async函数中,在这种情况下可以await编辑。)

因此,将Error转换为Promise拒绝。您无法在try..catch块中捕获它,原因很简单,try..catch在抛出错误之前就已经过了! (同样,例外是当你从async函数调用它时。如果你是await异步函数,try..catch块将起作用。在这种情况下try..catch 1}}块被视为添加Promise#catch函数。)

您最终必须使用普通Promise#catch方法或Promise#then的第二个参数来捕获async函数中的错误:

getNewTokens('no-such-refresh-token', 1)
    .then(function(tokens) {
        console.log(tokens);
    }, function(error) {
        console.log(error.message);
    });

答案 1 :(得分:7)

我想以一种合理且可读的方式提交此信息,以使用async / await处理错误。

const value = await asyncFunction().catch(err => new Error(err))
if (value instanceof Error) return res.status(500).send('There was an error doing something')

通过添加.catch()方法,返回一个 Error将其分配给 value 变量,我们可以确定变量中会存在一些值。唯一需要的另一行代码是if语句,以测试该值是否为Error的实例。如果由于某种原因被捕获,那肯定是Error的instance(我们的代码确保了此错误),并且我们的程序可以安全地处理该情况(在上述情况下,我们将返回500作为服务器响应,从而阻止了该程序因asyncFunction中的错误而执行任何危险代码)。

我有意将此行写成两行,以突出这一事实:它可以简洁地编写,并避免使用try / catch块,许多人不喜欢阅读(我本人就是其中之一)。

如果您喜欢阅读try / catch区块,那么恭喜您。我只是发现它使代码看起来很混乱。那好吧。 ¯\_(ツ)_/¯

答案 2 :(得分:4)

async / await和错误处理中初学者的实用答案

您不能在未使用 async 声明的函数之外使用等待语法,如此...

myAsyncFunction().then(() => console.log('here'));

所以最终,您必须使用旧的承诺方式来使用声明为 async 的函数

async function getUser(username) {
  try {
    return await db.users.get({ username });
  } catch (err) {
    return Promise.reject(err);
  }
}

因为它是承诺。

现在要实际处理然后 - catch 方式中的错误,你必须像这样构建你的异步函数......

getUser()
.then(user => console.log(user))
.catch(err => console.error(err));

然后你就可以像普通的Promise一样使用它,就像这样的异步方法......

async function getJoffery() {
  try {
    return await getUser('joffery');
  } catch (err) {
    return Promise.reject(err);
  }
}

或者你猜对了,使用await在异步函数中使用它。

{{1}}