从中间件中的Promise调用"next()"会导致“下一个不应被多次调用" [英] Calling 'next()' from promises in a middleware causes 'next shouldn't be called more than once'

查看:397
本文介绍了从中间件中的Promise调用"next()"会导致“下一个不应被多次调用"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我将代码从Express更改为Restify.老实说,我不确定它以前是否曾经发生过,但我想确实是这样.

基本上,在我的中间件中,我调用一个承诺方法,当它解析后,我调用next,并在下一个中间件中执行其他操作.当它被拒绝时,在某些情况下,我也想正确地调用next.否则,它必须调用将err传递给next的错误中间件.

somePromise()
.then(()=>{
    next();
})
.catch((err)=>{
    if(err.someatt) next();
    else next(err)
});

它可以很好地与somePromise的预期结果一起使用.问题是nextthen-catch链约束.并且在下一个中间件中引发错误时,它会调用catch方法并再次调用next

我发现next具有属性called,并且在再次调用next之前将其设置为false时,我摆脱了错误.但这当然是一种反模式.而且我在另一个也使用了promises的中间件中遇到了同样的问题(按预期方式调用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()回调中引发的错误而调用.

这个很棒的答案借来的非常有用的流程图说明了.then(onFulfilled, onRejected).then(onFulfilled).catch(onRejected)之间的区别:

Recently I changed my code from Express to Restify. I'm honestly not sure if it used to happen before, but I guess it did.

Basically in my middleware I call a promisified method and when it resolves I call next and do other stuff in the next middleware. When it is rejected I also want to call next with no errors in some cases. Otherwise it must call the error middleware passing err to next.

somePromise()
.then(()=>{
    next();
})
.catch((err)=>{
    if(err.someatt) next();
    else next(err)
});

It works fine with the expected results of somePromise. The problem is that next is bound by the then-catch chain. And when an error is thrown in the next middleware it invokes the catch method and calls next again!

I found out that next has an attribute called and when I turn it to false before calling next again I get rid of the the errors. But of course it is an antipattern. And I'm having the same problem in a different middleware that I also used promises (calling next as expected and then calling it again in the catch statement).

Anyone else had a problem like that?

解决方案

Change your chain to this:

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
});

The optional second argument of .then() acts as a .catch() callback, but is only invoked for errors thrown higher up in the chain, and is not invoked for errors thrown in the adjacent .then() callback.

A very helpful flowchart borrowed from this awesome answer demonstrates the difference between .then(onFulfilled, onRejected) and .then(onFulfilled).catch(onRejected):

这篇关于从中间件中的Promise调用"next()"会导致“下一个不应被多次调用"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆