我如何超速缓慢连接中间件,而是返回节点响应?

我有一个使用Connect的节点服务器来插入一些中间件,这些中间件试图转换node-http-proxy的响应stream。 偶尔,这种转换可能会非常缓慢,在这种情况下,最好只返回一个不包含转换的响应,或者包含部分应用程序。

在我的应用程序中,我试图在转换中间件的上下文中使用setTimeout来调用next毫秒。 这通常工作,但暴露的竞争条件,如果中间件已经调用next ,然后setTimeout触发,并发生相同的错误,如下所示: Error: Can't set headers after they are sent.

最终,我发展了setTimeout ,以Error实例作为第一个参数,然后在我的中间件链中捕获该错误,并假设res.headersSentfalse ,然后开始通过res.end.call(res)发送响应。 这工作,令人惊讶的是我可以设置超时几乎没有和响应会发生快得多,是完整的。

我觉得这最后一个方法是一个黑客,并不能免受相同的竞争条件,但也许似乎是更有弹性一点。 所以我想知道Node和Connect处理这种事情有什么样的惯用方法。

我该如何解决慢中间件的超时问题,并简单地返回响应stream?

目前这似乎是做我想要的,或多或less,但再次感到有点毛病。

 let resTimedout = false; const timeout = setTimeout(() => { if (!resTimedout) { resTimedout = true; next(); } }, 100); getSelectors(headers, uri, (selectors) => { const resSelectors = Object.keys(selectors).map((selector) => { ... }; const rewrite = resRewrite(resSelectors); rewrite(req, res, () => { if (!resTimedout) { resTimedout = true; clearTimeout(timeout); next(); } }); }); 

setTimeout返回超时的id,所以你可以运行clearTimeout传入id。 所以当转换完成之后,请在下一次调用之前清除超时。

 var a = setTimeout(()=>{}, 3000); clearTimeout(a); 

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

从Bluebird或Q库使用async.timeoutPromise.timeout

您可以消除对全局variables的需求并根据请求来决定:

 const rewrite = resRewrite(resSelectors); rewrite(req, res, () => { // set a timer to fail the function early let timer = setTimeout(() => { timer = null; next(); }, 100); // do the slow response transformation transformResponse((err, data) => { // eg. callback handler clearTimeout(timer); if (timer) next(); }); }); 

怎么运行的

如果计时器首先结束,它将自己设置为空,并调用next()。 当转换函数结束时,它将看到超时值为空,不会调用next()。

如果响应转换更快,则清除超时以防止稍后运行。