1

我正在使用node-request将请求发送到服务器以获取一些报告。问题是服务器需要一些时间来生成报告,所以它以报告状态响应。我正在使用setInterval()函数检查报告状态,并clearInterval()在服务器发送ready响应时使用。但是使用这种方法,即使在我使用之后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- 在超时后发出另一个请求,重复直到响应的状态代码为ready. 如果状态就绪 - 退出循环(或清除间隔)并运行@processReport.

我尝试提出承诺请求,并将其放入setInterval,但结果是一样的。

PS我不控制服务器,所以我不能改变它响应或处理报告的方式。

4

2 回答 2

1

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

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
});
于 2015-09-01T23:36:27.463 回答
1

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

而是将 asetTimeout放入成功处理程序中,并在(且仅当)收到响应后重试。
使用 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))
于 2015-09-02T12:23:40.057 回答