【问题标题】:AJAX Webworker Polling with setTimeout使用 setTimeout 进行 AJAX Webworker 轮询
【发布时间】:2016-07-25 13:36:10
【问题描述】:

我正在尝试让网络工作者每秒左右轮询同一台机器上的网络服务器接口。我读过的大多数文章都说要避免使用 setInterval 并改用 setTimeout,但我还没有找到使用 AJAX 而不是 Jquery 的示例。

我目前的代码如下:

(function poll() {
    setTimeout(function() {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
        if (xhr.status === 200) {
            responseObject = JSON.parse(xhr.responseText);
            var newContent = '';
            newContent += responseObject.cmd;
            console.log(newContent);
        }
    }
    xhr.open('GET', 'http://localhost:8194/screen_update/1000', true);
    xhr.send(null);
    setTimeout(poll, 1000);
}, 1000);
})();

首选的输出是每秒轮询服务器,理论上这应该足以让响应通过。我一次只需要一个请求,所以如果我最终收到一个请求超过一秒钟的请求,它只会转储请求(而不是排队)并发出一个新请求。

上面的代码轮询正常,但没有完成 2 秒,所以我显然把我的 setTimeout 搞混了。我在哪里更正此代码?

【问题讨论】:

  • 把超时放在onoad中

标签: javascript ajax settimeout web-worker polling


【解决方案1】:

几天前我就这样做了.. 虽然它可能不是最优雅的,但到目前为止它运行良好。 我让工作人员处理超时/检查间隔,而不是主 JS。所以我想这是 UI 不需要处理的另一件事。这是我的工人代码:

function checkStatus() {    
    console.log("statusCheck started");

    var ajaxRequest;
    try { ajaxRequest = new XMLHttpRequest(); // Opera 8.0+, Firefox, Safari
    } catch (e) { try { // Internet Explorer Browsers
            ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) { try {
                ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) { // Something went wrong
                console.error("AJAX not possible");
                return false;
            }
        }
    }


    // Create a function that will receive data sent from the server
    ajaxRequest.onreadystatechange = function() {
    if(ajaxRequest.readyState == 4) {

            self.postMessage(ajaxRequest.responseText);

            var timer;
            timer = self.setTimeout(function(){
                checkStatus();
            }, 1000);

        }
    }

    ajaxRequest.open("GET", "/worker_statusCheck.php", true);
    ajaxRequest.send(null);

}



this.onmessage  =   function(e){
    checkStatus(); // the message comes in just once on pageLoad
};

【讨论】:

  • 顺便说一句:这不会每秒检查一次。这会在 AJAX 响应成功后一秒再次检查。
【解决方案2】:

定义一个变量来确定ajax 是否完成。如果在ajax还没有完成的时候调用了函数,可以退出函数等待下一次调用。

var stillWorking = false;

(function poll() {
   if(stillWorking) return false; 
   stillWorking = true;
    setTimeout(function() {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
        if (xhr.readyState == 4) stillWorking = false;
        if (xhr.status === 200) {
            responseObject = JSON.parse(xhr.responseText);
            var newContent = '';
            newContent += responseObject.cmd;
            console.log(newContent);

        }
    }
    xhr.open('GET', 'http://localhost:8194/screen_update/1000', true);
    xhr.send(null);
    setTimeout(poll, 1000);
}, 1000);
})();

【讨论】:

    【解决方案3】:

    当您收到 AJAX 的响应时,您可以调用相同的函数。这样就不需要检查当前 AJAX 是否正在处理中。

    function poll() {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange= function() {
    
            if (xhr.status === 200) {
                responseObject = JSON.parse(xhr.responseText);
                var newContent = '';
                newContent += responseObject.cmd;
                console.log(newContent);
    
            }
            if (xhr.readyState == 4)
            {
                setTimeout(function(){ poll();},1000);
            }
        }
        xhr.open('GET', 'http://localhost:8194/screen_update/1000', true);
        xhr.send(null);
    };
    setTimeout(function(){ poll();},1000);
    

    如果你想使用 onload 回调,那么回调代码应该是

     xhr.onload= function() {
            if (xhr.status === 200) {
                responseObject = JSON.parse(xhr.responseText);
                var newContent = '';
                newContent += responseObject.cmd;
                console.log(newContent);
    
            }
            setTimeout(function(){ poll();},1000);
        }
    

    【讨论】:

    • 如果状态码不是 200,这将停止 ajax 请求
    • 哦,是的...如果 state 是 4,我们必须检查 ajax state。
    • 您是否有任何理由从初稿中的 onload 更改为 onreadystatechange?我的初稿工作正常,我还能将 xhr.readyState 与 xhr.onload 一起使用吗?
    【解决方案4】:

    因为你使用的是HTML5 WebWorker,可能你可以使用使用promise的window.fetchhttps://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),我认为浏览器支持几乎是一样的。

    这是一个例子:

    ((url, INTERVAL, configs) => {
      const MAX_ERRORS = 4;
      let errors = 0;
      var poll = () => window.setTimeout(getData, INTERVAL);
      
      function getData() {
        return window
          .fetch(url, configs)
          .then(res => res.json())
          .then(data => {
            errors = 0;
            poll();    
            return data;
          })
          .then((data) => {
            console.log("new data available", data);
          })
          .catch(() => {
            if(errors >= MAX_ERRORS) {
              console.log("GIVING UP");
              return;
            }
            
            errors += 1;
            return poll();
          })
        ;
      }
     
      
      return poll();
    })("http://jsonplaceholder.typicode.com/posts/1", 1000, {
      method: 'GET' 
    });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-01
      • 2016-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-11
      相关资源
      最近更新 更多