【问题标题】:Node and async/await, promises … which solution is best?Node 和 async/await,promises ... 哪个解决方案最好?
【发布时间】:2016-05-15 12:08:26
【问题描述】:

使用 Node 和 Express 与 Babel 合作,并尝试找出 async/await 和 Promise 之间的最佳方法。

关键要求:

  • 能够传递我自己的错误
  • 不造成阻塞
  • 以更多 ES6/ES7 方式解决问题

我想出了这些:

承诺:

loadByIdPromises: function (req, res, next, _id) {
  console.log('loadByIdc: ', _id);
  Artwork.loadById( { _id } )
    .then( (artwork) => {
      req.artwork = artwork;
      next();
    })
    .catch( (err) => next(new NoDataError('cannot find by ID')));
}

异步/等待:

loadByIdAsync: async function (req, res, next, _id) {
  console.log('loadByIdb: ', _id);
  try {
    req.artwork = await Artwork.loadById( { _id } );
    next();
  } catch (err) {
    next(new NoDataError('cannot find by ID'));
  }
}

或带包装的异步/等待

let wrap = fn => (...args) => fn(...args).catch(args[2]);
loadByIdAsyncWrap: wrap( async function (req, res, next, _id) {
  console.log('loadByIda: ', _id);
  req.artwork = await Artwork.loadById( { _id } );
  next();
}),

Promise 看起来很干净,但当事情变得复杂时可能会导致级联。但是有一个漂亮而干净的错误处理。

Async/Await 看起来很干净,但除了整个 try/catch 之外,我不知道如何从 await 中抛出错误。

带有包装器的异步/等待似乎很简单,并且(至少在这种情况下 - 节点快速路由器)可以很好地处理错误(但无法设置我自己的)。但是包装器是特定于 req,res,next 参数的,在我看来它是一些外来的东西(比如我们的 css2/3 幸福之前的 html 中的额外 div)。

选择什么方法?感谢您的建议。

【问题讨论】:

  • 你看koa了吗:github.com/koajs/koa
  • 您在基于 Promise 的版本中可能存在潜在问题,也许在其他版本中 - 调用 next() 时引发的任何异常都可能最终传播到链上。你可能想要load().then(do_stuff).then(next, (err) => next(new Error))
  • 使用try/catch进行错误处理有什么问题?
  • @Sergey_Ksenofontov 是的,我已经看过了,它看起来很棒,但我想和大多数人在一起(表达):)
  • 谢谢@Alnitak 我知道了。我必须将next().then(do_stuff) 块移动到最后一个.then,对吗? wrap 函数暴露了我手动做的同样的问题,对吧?

标签: javascript node.js asynchronous promise


【解决方案1】:

我会使用 Promise 方法,因为 async / await 还不是主流。

但是我看到了一个潜在的问题,即您对next() 的调用是初始块中,这意味着您可以成功完成第一阶段,然后调用next(),但是如果that 抛出一个未被捕获的错误,调用堆栈将返回一个级别,该错误被您的第一个 .catch() 块捕获。即使真正的错误在 next() 处理程序中,您也会生成 cannot find by ID 错误。

我建议这样做:

function (req, res, next, _id) {
  console.log('loadByIdc: ', _id);
  Artwork.loadById( { _id } )
    .then((artwork) => req.artwork = artwork)
    .then(next, (err) => next(new NoDataError('cannot find by ID')));
}

这仍然给您留下一个问题,即如何.catch next 可能引发的任何异常,但至少您不会被捕获该异常的点误导。

【讨论】:

  • 错误处理方面对我来说是新的,谢谢@Alnitak。我会赞成你的回答,但我不能。
  • “这仍然给您留下一个问题,即如何 .catch 任何可能由next 抛出的异常” 它会被捕获并在then 返回的承诺。上面的代码应该要么处理拒绝(通过.catch(err => ...)),要么将承诺链传递给可以做的事情。最简单的方法(如果不传递它)是将传递给最终.then 的第二个处理程序移动到后面的.catch 中,以便它处理由next 抛出引起的拒绝。 (cc @DavidC)
猜你喜欢
  • 2014-03-24
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 2017-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多