【问题标题】:How to use setInterval (with clearInterval) to send requests using Bluebird Promises?如何使用 setInterval (with clearInterval) 使用 Bluebird Promises 发送请求?
【发布时间】:2015-09-01 22:49:54
【问题描述】:

我使用node-request 将请求发送到服务器以获取一些报告。问题是服务器需要一些时间来生成报告,所以它以报告状态响应。我正在使用setInterval() 函数检查报告状态,并在服务器发送ready 响应时使用clearInterval()。但是使用这种方法,即使在我使用clearInterval 之后,早期请求的响应也会不断出现,并且响应处理程序会一次又一次地运行。这不会造成太大的伤害,但我仍然相信可以做得更好。

这是我的代码:

checkForReportReady = setInterval =>
  @request URL, options, (err, res, body) =>
    console.log err if err
    body = JSON.parse body

    if body['status'] is 'ready'
      clearInterval checkForReportReady
      @processReport body
  , 1000

我需要什么:发出请求,等待响应,检查状态,如果状态不是ready - 超时后发出另一个请求,重复直到响应的状态码为@ 987654328@。如果状态为就绪 - 退出循环(或清除间隔)并运行 @processReport

我尝试提出promisified request,并将其放入setInterval,但结果是一样的。

附:我不控制服务器,因此我无法更改它响应或处理报告的方式。

【问题讨论】:

    标签: javascript node.js promise bluebird node-request


    【解决方案1】:

    我建议不要将请求放在间隔回调中。当他们 a) 失败 b) 花费的时间超过间隔时,这可能会变得很糟糕。

    而是将setTimeout 放在成功处理程序中,并在(且仅当)收到响应后重试。
    使用 Promise 很容易做到这一点:

    request = Promise.promisifyAll require 'request'
    getReport = () =>
      request URL, options
      .spread (res, body) =>
        body = JSON.parse body
        if body.status is 'ready'
          body
        else
          Promise.delay 1000
          .then getReport # try again
    
    getReport().then(@processReport, (err) -> console.log(err))
    

    【讨论】:

      【解决方案2】:

      您似乎可以在响应处理程序中使用setTimeout()

      function checkForReportReady() {
          request(URL, options, function(err, res, body) {
              if (err) {
                  console.log(err);
              } else {
                  if (body.status === "ready") {
                      processReport(body);
                      // do any other processing here on the result
                  } else {
                      // try again in 20 seconds
                      setTimeout(checkForReportReady, 20*1000);
                  }
              }
          });
      }
      

      这将运行一个请求,等待响应,检查响应,如果它准备好了,它会处理它,如果它没有准备好,它会等待一段时间,然后开始另一个请求。它永远不会同时处理一个以上的请求。


      如果你想使用 Bluebird Promise,你也可以这样做,尽管在这种情况下它似乎并没有特别改变复杂性:

      var request = Promise.promisifyAll(require('request'));
      
      function checkForReportReady() {
          return request(URL, options).spread(function(res, body) {
              if (body.status === "ready") {
                  return body;
              } else {
                  // try again in 20 seconds
                  return Promise.delay(20 * 1000).then(checkForReportReady);
              }
          });
      }
      
      checkForReportReady().then(function(body) {
          processReport(body);
      }, function(err) {
          // error here
      });
      

      【讨论】:

      猜你喜欢
      • 2014-10-08
      • 2018-03-05
      • 2011-08-24
      • 2015-10-08
      • 1970-01-01
      • 2015-04-17
      • 2021-12-27
      相关资源
      最近更新 更多