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

问题描述 投票:2回答:3

两个尝试打印Promise { <pending> }和第二个有Unhandled Promise Rejection Warning。我已经成功使用了.then和.catch的Promises,但有些东西我想使用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'
  }
}
javascript node.js async-await
3个回答
16
投票

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

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

所以投掷一个Error被转换成Promise拒绝。你不能在try..catch区块中捕获它,原因很简单,因为在抛出错误之前try..catch已经过了! (同样,例外情况是你从async函数调用它。如果你是awaiting异步函数,try..catch块将工作。在这种情况下,try..catch块被视为添加了Promise#catch函数。)

你最终必须使用正常的async方法或Promise#catch的第二个参数从Promise#then函数中捕获错误:

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

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的实例。如果它因任何原因被捕获,它肯定会是一个错误的实例(我们的代码确保这一点),并且我们的程序可以安全地处理该场景(在上面的例子中,我们返回500作为服务器响应,从而阻止程序由于asyncFunction中的错误而执行任何危险代码)。

我有意写了两行,以突出这一事实,这可以简洁地写,避免使用try / catch块,许多人不喜欢阅读(我自己就是一个)。

如果你阅读try / catch积木很酷,恭喜你。我发现它使代码看起来很笨拙。那好吧。 ¯\_(ツ)_/¯


3
投票

A practical answer for beginners in async/await and error handling

你不能在未使用async声明的函数之外使用await语法,就像这样......

async function myAsyncFunction() {
  // code
}

所以最终,你必须使用旧的Promise方法来使用声明为async的函数

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

因为它是一种承诺。

现在要实际处理像你习惯的那样的错误,你必须构建你的异步函数,就像这样......

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

然后你可以像在异步方法之外的普通Promise一样使用它...

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

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

async function getJoffery() {
  try {
    return await getUser('joffery');
  } catch (err) {
    return Promise.reject(err);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.