我如何超速缓慢连接中间件,而是返回节点响应?
我有一个使用Connect的节点服务器来插入一些中间件,这些中间件试图转换node-http-proxy的响应stream。 偶尔,这种转换可能会非常缓慢,在这种情况下,最好只返回一个不包含转换的响应,或者包含部分应用程序。
在我的应用程序中,我试图在转换中间件的上下文中使用setTimeout
来调用next
毫秒。 这通常工作,但暴露的竞争条件,如果中间件已经调用next
,然后setTimeout
触发,并发生相同的错误,如下所示: Error: Can't set headers after they are sent.
最终,我发展了setTimeout
,以Error
实例作为第一个参数,然后在我的中间件链中捕获该错误,并假设res.headersSent
为false
,然后开始通过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.timeout
或Promise.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()。
如果响应转换更快,则清除超时以防止稍后运行。