AJAX Webworker 使用 setTimeout 进行轮询

AJAX Webworker Polling with setTimeout

我试图让网络工作者每隔一秒左右轮询同一台机器上的网络服务器界面。我读过的大多数文章都说要避免 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。我在哪里更正此代码?

定义一个变量来确定 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);
})();

您可以在收到 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);
    }

我几天前就这样做了..虽然它可能不是最优雅的,但到目前为止它运行良好。 我让工作人员处理超时/检查间隔,而不是主要的 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
};

因为你用的是HTML5 WebWorker,可能你可以用window.fetch,它使用了promises(https://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' 
});