为什么在使用setTimeout的后续调用中未定义retry_interval

时间:2018-08-20 09:00:12

标签: javascript scope

我在函数中调用setTimeout遇到问题。 setTimeout递归调用get_zone_counts函数(仅在错误情况下)。第一次调用setTimeout时,根据函数的第一次调用正确设置了retry_delay参数。但是在随后的setTimeout调用中,retry_delay参数是不确定的。

为什么会这样,我该如何解决?

代码如下:

const request = require('request');

// server not connected for this test
const url = "http://192.168.1.23/api/data/live?format=JSON";

function handle_zone_count_response(body, container) {
    // this function simply parses the response message
    console.log("handle_zone_count_response called");
}

function get_zone_counts(url, retry_delay) {
    request.get(url, function(error, res, body) {
        if(error) {
        console.log("error: ", error);
        console.log(`setting timer to retry zone count requests in ${retry_delay} msecs`);
        // set timer to try again after retry_delay
        setTimeout(get_zone_counts, retry_delay, url);
        } else {
            console.log(body);
            handle_zone_count_response(body, zone_counts);
        // print zone_counts
            console.log("zone counts: ", zone_counts);
        }
    });
}

get_zone_counts(url, 5000);

示例输出:

error:  { Error: connect ETIMEDOUT 192.168.1.23:80
    at Object._errnoException (util.js:1003:13)
    at _exceptionWithHostPort (util.js:1024:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1195:14)
  errno: 'ETIMEDOUT',
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '192.168.1.23',
  port: 80 }
setting timer to retry zone count requests in 5000 msecs
error:  { Error: connect ETIMEDOUT 192.168.1.23:80
    at Object._errnoException (util.js:1003:13)
    at _exceptionWithHostPort (util.js:1024:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1195:14)
  errno: 'ETIMEDOUT',
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '192.168.1.23',
  port: 80 }
setting timer to retry zone count requests in undefined msecs
error:  { Error: connect ETIMEDOUT 192.168.1.23:80
    at Object._errnoException (util.js:1003:13)
    at _exceptionWithHostPort (util.js:1024:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1195:14)
  errno: 'ETIMEDOUT',
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '192.168.1.23',
  port: 80 }
setting timer to retry zone count requests in undefined msecs

1 个答案:

答案 0 :(得分:3)

您的递归调用是

setTimeout(get_zone_counts, retry_delay, url);

这意味着:在get_zone_counts毫秒后使用参数retry_delay调用url。也就是说,retry_delay不会传递到任何后续调用。

如果要将与初始调用相同的retry_delay传递给递归调用,请将其添加到setTimeout参数列表的末尾:

setTimeout(get_zone_counts, retry_delay, url, retry_delay);

这基本上与

相同
setTimeout(() => get_zone_counts(url, retry_delay), retry_delay);

看起来更直观。