简体   繁体   English

如何使用setInterval(带有clearInterval)使用Bluebird Promises发送请求?

[英]How to use setInterval (with clearInterval) to send requests using Bluebird Promises?

I'm using node-request for sending the requests to server to get some report. 我正在使用node-request将请求发送到服务器以获取一些报告。 The thing is server needs some time to generate the report, so it responses with the report state. 问题是服务器需要一些时间来生成报告,因此它以报告状态进行响应。 I'm checking the report state with setInterval() function, and use clearInterval() when server sends ready response. 我正在使用setInterval()函数检查报告状态,并在服务器发送ready响应时使用clearInterval() But with this approach, even after I use clearInterval , responses of earlier requests keep coming, and the response handler runs again and again. 但是,使用这种方法,即使在我使用clearInterval ,早期请求的响应也会继续出现,并且响应处理程序会一次又一次地运行。 This does not cause a lot of harm, but still I believe it can be done better. 这不会造成很大的伤害,但是我仍然相信可以做得更好。

Here is my code: 这是我的代码:

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

What I need : make a request, wait for response, check the status, if status is not ready - make another request after some timeout, repeat until the status code in response is ready . 我需要的是 :发出请求,等待响应,检查状态,如果状态尚未ready -超时后再次发出请求,请重复直到响应的状态代码ready为止。 If the status is ready - exit the loop (or clear the interval) and run @processReport . 如果状态为就绪,请退出循环(或清除间隔)并运行@processReport

I tried to make promisified request, and put it into setInterval , but the result was the same. 我试图发出有条件的请求,并将其放入setInterval ,但结果是相同的。

PS I do not control the server, so I can't change the way it responds or deals with the report. PS:我无法控制服务器,因此无法更改其响应或处理报告的方式。

It seems like you can just use a setTimeout() in your response handler: 似乎您可以只在响应处理程序中使用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);
            }
        }
    });
}

This will run one request, wait for the response, check the response, then if it's ready it will process it and if it's not ready, it will wait a period of time and then start another request. 这将运行一个请求,等待响应,检查响应,然后准备就绪将对其进行处理,如果尚未准备就绪,它将等待一段时间,然后启动另一个请求。 It will never have more than one request in-flight at the same time. 它永远不会同时有多个请求。


If you want to use Bluebird promises, you can do that also, though in this case it doesn't seem to change the complexity particularly much: 如果您想使用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
});

I would recommend not to put requests in an interval callback. 我建议不要将请求放在间隔回调中。 This can get ugly when they a) fail b) take longer than the interval. 当他们a)失败b)花费比间隔更长的时间时,这可能会变得很丑陋。

Instead put a setTimeout in the success handler and try again after (and only if) receiving a response. 而是将setTimeout放入成功处理程序中,然后(仅)在收到响应后重试。
This is rather easy with promises: 有了诺言,这很容易:

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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM