【问题标题】:How can I timeout slow Connect middleware and instead return the Node response?如何使慢速连接中间件超时并返回节点响应?
【发布时间】:2017-01-18 02:30:52
【问题描述】:

我有一个 Node 服务器,它使用 Connect 插入一些中间件,这些中间件试图从 node-http-proxy 转换响应流。有时,这种转换可能会很慢,在这种情况下,最好只返回一个不包含转换或包含它们的部分应用的响应。

在我的应用程序中,我尝试使用setTimeout 在转换中间件的上下文中经过几毫秒后调用next。这通常有效,但会暴露一个竞争条件,如果中间件已经调用了next,然后setTimeout 触发并且发生同样的错误,看起来像:Error: Can't set headers after they are sent.

最终我将setTimeout 改进为以Error 实例作为其第一个参数来调用next,然后在我的中间件链中稍后会捕获该错误并假设res.headersSentfalse 将开始发送通过res.end.call(res)回复。这很奏效,令人惊讶的是,我可以将超时设置为几乎为零,并且响应会发生得更快并且是完整的。

我觉得最后一种方法有点像 hack 并且不能免受相同的竞争条件的影响,但可能看起来更有弹性。所以我想知道 Node 和 Connect 有哪些惯用的方法来处理这种事情。

如何让慢速中间件超时并简单地返回响应流?

目前这似乎或多或少符合我的要求,但又感觉有点恶心。

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

【问题讨论】:

标签: javascript node.js connect node-http-proxy


【解决方案1】:

setTimeout 返回超时的 id,因此您可以通过传入 id 运行 clearTimeout。因此,当转换完成后,只需在调用 next 之前清除超时。

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

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

【讨论】:

    【解决方案2】:

    使用来自BluebirdQ 库的async.timeoutPromise.timeout

    【讨论】:

      【解决方案3】:

      您可以消除对全局变量的需求,并根据请求决定这一点:

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

      工作原理

      如果计时器先结束,它会将自己设置为 null 并调用 next()。当transform函数结束时,会看到timeout为null,不会调用next()。

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

      【讨论】:

        猜你喜欢
        • 2017-07-23
        • 2017-03-08
        • 1970-01-01
        • 1970-01-01
        • 2019-09-07
        • 1970-01-01
        • 1970-01-01
        • 2019-10-23
        • 1970-01-01
        相关资源
        最近更新 更多