代码之家  ›  专栏  ›  技术社区  ›  igorludi

递归异步延迟承诺重叠

  •  -1
  • igorludi  · 技术社区  · 7 年前

    用例如下:我想每隔x毫秒查询一个URL,直到得到一个肯定的答复。

    我正试图在JS(节点)中实现这一点,并且对于多个这样的请求有一个问题。 如果我只启动其中一个“链调用”,一切都会正常工作。

    但如果我试着平行地运行一些程序,“最后一个程序获胜”(第一个程序永远不会解决)。我似乎在使用对同一个对象或某物的引用,但我无法理解。

    注意“mastercounter”和“id”变量是如何被覆盖的,尽管它们是作为参数按值传递的。

    以下是工作代码(其中“第二”胜于“第一”):

    (如果安装请求包,则可以与节点一起运行 https://www.npmjs.com/package/request )

    var req = require('request');
    
    const ASK_EVERY_MS = 500;
    const AT_MOST_MS = 5000;
    
    var childRecursive = (t, resolve, reject, t0, id, masterCounter) => {    
        var duration = process.hrtime(t0);    
        duration = (duration[0] * Math.pow(10, 9) + duration[1]) / Math.pow(10, 6)
        if (duration + t > AT_MOST_MS) {
            reject('timeout');
        } else {
            var options = {
                url: 'http://www.google.com',
                json: false,
                headers: {
                    timeout: 1000
                }
            };
            callback = function (error, response, body) {
                if (!error) {
                    console.log('body', body.substring(0, 100));
                    if (masterCounter % 5 == 0) {
                        return resolve("success!!!");
                    } else {
                        return childRecursive(ASK_EVERY_MS, resolve, reject, t0, id, masterCounter + 1, req);
                    }
                } else {
                    console.log('problem with submission GET request: ' + error);
                    return reject(error);
                }
            }
            console.log(id + ' masterCounter is ' + masterCounter);
            setTimeout(() => {
                console.log(id + ' requesting...');
                req.get(options, callback);
            }, t);
        }
    };
    
    var t0 = process.hrtime();
    var first = new Promise((resolve, reject) => childRecursive(0, resolve, reject, t0, 'FIRST', 101));
    first.then(() => {
        console.log('FIRST done');
    });
    var scnd = new Promise((resolve, reject) => childRecursive(0, resolve, reject, t0, 'SECOND', 201));
    scnd.then(() => {
       console.log('SECOND done');
    });
    

    输出:

    FIRST masterCounter is 101
    SECOND masterCounter is 201
    FIRST requesting...
    SECOND requesting...
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 202
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 202
    SECOND requesting...
    SECOND requesting...
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 203
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 203
    SECOND requesting...
    SECOND requesting...
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 204
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 204
    SECOND requesting...
    SECOND requesting...
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 205
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND masterCounter is 205
    SECOND requesting...
    SECOND requesting...
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    SECOND done
    body <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="hr"><head><meta content
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Bergi    7 年前

    你的问题是 implicitly global callback 变量。它应该是

    var callback = function (error, response, body) { /*
    ^^^ */
    

    function callback(error, response, body) {
    

    总是 use strict mode 为了避免这样的错误!