Javascript 从中间件中的承诺调用“next()”会导致“next不应被多次调用”

Javascript 从中间件中的承诺调用“next()”会导致“next不应被多次调用”,javascript,node.js,express,promise,restify,Javascript,Node.js,Express,Promise,Restify,最近我把我的代码从Express改为Restify。老实说,我不确定这以前是否发生过,但我想是的 基本上,在我的中间件中,我调用一个promisified方法,当它解决时,我调用next并在下一个中间件中执行其他操作。当它被拒绝时,我也希望在某些情况下无错误地调用next。否则,它必须调用将err传递给next的错误中间件 它可以很好地工作,并获得预期的结果。问题是,next受当时的捕获链约束。当在下一个中间件中抛出错误时,它将调用catch方法并再次调用next 我发现next调用了一个属性,

最近我把我的代码从Express改为Restify。老实说,我不确定这以前是否发生过,但我想是的

基本上,在我的中间件中,我调用一个promisified方法,当它解决时,我调用next并在下一个中间件中执行其他操作。当它被拒绝时,我也希望在某些情况下无错误地调用next。否则,它必须调用将err传递给next的错误中间件

它可以很好地工作,并获得预期的结果。问题是,next受当时的捕获链约束。当在下一个中间件中抛出错误时,它将调用catch方法并再次调用next

我发现next调用了一个属性,当我在再次调用next之前将其设置为false时,我消除了错误。但它当然是一种反模式。我在另一个中间件中遇到了同样的问题,我也使用了Promissions按预期调用next,然后在catch语句中再次调用它


其他人有这样的问题吗?

将您的链更改为:

somePromise().then(() => {
  next();
}, err => {
  // error occurred in somePromise()
  if(err.someatt) next();
  else next(err);
}).catch(err => {
  // error occurred in .then()'s next()
  // don't call next() again
});
的可选第二个参数用作.catch回调,但仅对链中较高位置抛出的错误调用,而不对相邻.then回调中抛出的错误调用

借用的一个非常有用的流程图演示了.ThenOnCompleted、onRejected和.ThenOnCompleted.catchonRejected之间的区别:


将您的链更改为:

somePromise().then(() => {
  next();
}, err => {
  // error occurred in somePromise()
  if(err.someatt) next();
  else next(err);
}).catch(err => {
  // error occurred in .then()'s next()
  // don't call next() again
});
的可选第二个参数用作.catch回调,但仅对链中较高位置抛出的错误调用,而不对相邻.then回调中抛出的错误调用

借用的一个非常有用的流程图演示了.ThenOnCompleted、onRejected和.ThenOnCompleted.catchonRejected之间的区别:


您可以在第一次调用next时尝试/catch,这样异常就不会传播到.catch处理程序中。或者您可以使用这两个参数。然后,在第一个参数中出现拒绝/异常。然后回调不会转到该捕获处理程序。是!我已经做了。问题是我需要调用错误中间件。我必须把它分成几个部分,这样我可以从try/catch调用它,从中间件堆栈中,您可以在第一次调用下一次时尝试/catch,这样异常就不会传播到.catch处理程序。或者您可以使用这两个参数。然后,在第一个参数中出现拒绝/异常。然后回调不会转到该捕获处理程序。是!我已经做了。问题是我需要调用错误中间件。我必须把它分成几个部分,这样我就可以从try/catch和中间件堆栈中调用它了。谢谢你的回答。但是如果我不能再次调用next,我就不能真正使用我的错误中间件,对吗@VictorFerreira如果您的中间件抛出错误,那么您就有一个需要修复的bug。要么你没有捕捉到一个令人烦恼的/外生的异常,要么你试图捕捉一个需要首先防止发生的愚蠢异常。有关术语的解释,请参见。我当然理解。但奇怪的是,调用next的中间件突然对应用程序中所有未捕获的错误负责。如果我没有使用catch,那么这个中间件就不会捕获它。应用程序得到的错误是“下一个不能调用多次”或“未捕获的承诺拒绝”。这不好,因为它是静默的,或者在使用我的模式时没有清楚地显示错误的真正含义,而在链末尾的.catch回调中显示的任何错误都是需要修复的错误的指示。记录他们的堆栈属性,它会准确地显示错误的来源。是的!这是一个很好的例子来说明为什么。成功处理程序,错误处理程序是模式,而不是通常所说的反模式。谢谢你的回答。但是如果我不能再次调用next,我就不能真正使用我的错误中间件,对吗@VictorFerreira如果您的中间件抛出错误,那么您就有一个需要修复的bug。要么你没有捕捉到一个令人烦恼的/外生的异常,要么你试图捕捉一个需要首先防止发生的愚蠢异常。有关术语的解释,请参见。我当然理解。但奇怪的是,调用next的中间件突然对应用程序中所有未捕获的错误负责。如果我没有使用catch,那么这个中间件就不会捕获它。应用程序得到的错误是“下一个不能调用多次”或“未捕获的承诺拒绝”。这不好,因为它是静默的,或者在使用我的模式时没有清楚地显示错误的真正含义,而在链末尾的.catch回调中显示的任何错误都是需要修复的错误的指示。记录它们的堆栈属性,它将显示e
错误的确切来源。是的!这是一个很好的例子来说明为什么。SuccessHandler,errorHandler是模式,而不是通常所称的反模式。