【问题标题】:Is the setInterval() an asynchronous function?setInterval() 是异步函数吗?
【发布时间】:2015-09-02 08:23:27
【问题描述】:

我每秒向服务器发送一个XMLHttpRequest,服务器将响应新消息。为了每秒调用一次XMLHttpRequest,我在SharedWorker 中使用setInterval() 函数。

但是,由于我每秒都在发出请求,所以我想知道setInterval() 是否是异步的?

例如,如果一个 XMLHttpRequest 请求“由于延迟”需要 3 秒才能完成,我会同时处理 3 个请求还是 setInterval() 等到第一个请求完成后再等待 1 秒并发送另一个请求?

这是我的代码

function checkQueue(url)
{
  var xhr = new XMLHttpRequest();
  xhr.addEventListener("load", reqListener);
  xhr.open('GET', url, true);
  xhr.send();
}


function reqListener ()
{
    var queue = JSON.parse(this.responseText);
    notifyAllPorts(queue);
    console.log(this.responseText);
}


setInterval(
    function() {
        checkQueue('/add-ons/icws/push.php') 
    }
, 1000);

【问题讨论】:

  • 它是异步的,但是你不会有 3 个请求同时进行,因为函数间隔是 1 秒。无论如何,提供的函数将每秒执行一次。
  • @MinusFour 那么我将至少有 2 个同时进行。如果服务器需要 10 秒来响应,那么请求将不断出现。我怎样才能防止这种情况发生?
  • 你可以通过承诺来做到这一点,如果问题是如何间隔承诺,我可以提供答案。
  • @MinusFour 它们可能是需要“大量时间”的请求..
  • setInterval 尝试最好以“n * 持续时间”间隔运行。但这与核心误解无关:“setInterval() 会等到第一个请求完成吗?”不,不像想象的那样。从setInterval 开始的所示 XHR 代码是 异步 并且将“几乎立即完成”;因此,如果 setInterval 等待(因为 异步代码已经完成运行)或者它如何为下一次超时安排自己,它甚至都无关紧要。

标签: javascript jquery asynchronous xmlhttprequest setinterval


【解决方案1】:

正如所指出的,它不会等到请求完成。这是间隔承诺的一种方法:

 function checkQueue(url, cb) {
     var xhr = new XMLHttpRequest();
     xhr.addEventListener("loadend", cb);
      xhr.addEventListener("load", reqListener);
     xhr.open('GET', url, true);
     xhr.send();
 }

function reqListener ()
{
    var queue = JSON.parse(this.responseText);
    notifyAllPorts(queue);
    console.log(this.responseText);
}

 var promise = Promise.resolve(true);

 setInterval(function () {
     promise = promise.then(function () {
         return new Promise(function (resolve) {
             checkQueue(yourUrlHere, resolve);
         });
     });
 }, 1000);

它将继续每秒添加要执行的请求,但如果超过 1 秒,它会延迟自己。

【讨论】:

  • 确保我在这里关注你。因此,如果一个请求需要 10 秒,它会创建一个包含请求的队列,一旦完成,它就会开始运行队列中的请求,直到它咳出?
  • 如果一个请求需要 10 秒,这将排队 8-9 个请求完成,但只会在最后一个完成后继续触发。也就是说,在一个小时内,它将排队 3600 份请愿书。如果请愿书都持续了 1 秒,那么所有 3600 次请愿书都将完成。如果一个请愿时间超过 1 秒,它会延迟队列中的下一个请愿,直到完成,从而导致少于 3600 个请愿。
  • 我对您的代码进行了一些调整,因为我正在体验此代码每秒生成一个新的 TCP 连接的问题。它不重用打开的 TCP 连接。请看看我发布的另一个问题stackoverflow.com/questions/32505128/… 谢谢你的帮助:)
  • 有人可以解释第 3 行和 setInterval 处理程序中的承诺吗?
【解决方案2】:

是的,你会遇到麻烦。无论您的请求处于何种状态,setInterval 都会像发条一样响起。

您最好在每个请求完成时使用setTimeout 启动一个点击计时器...所以:

function checkQueue(url)
{
  var xhr = new XMLHttpRequest();
  xhr.addEventListener("load", reqListener);
  xhr.open('GET', url, true);
  xhr.send();
}


function reqListener ()
{
    var queue = JSON.parse(this.responseText);
    notifyAllPorts(queue);
    console.log(this.responseText);
    setTimeout(
        function() {
            checkQueue('/add-ons/icws/push.php') 
        }, 1000);
}


checkQueue('/add-ons/icws/push.php') 

【讨论】:

  • 感谢您的回答。那么你将编码到底做什么?它如何保证一个请求将只开始一个完成?
  • ...因为我们只有在确定上一个请求完成后才启动一次性计时器(即在 XMLHttpRequest 的load 事件之后...您的回调被调用,因此请求已经完成了)。这意味着一旦上一个请求完成,我们将等待一秒钟再重新启动。正是你想要的,不是吗?
  • 我明白了。因此,此代码将确保除非现有请求完成,否则不会触发任何请求。如果服务器和工作人员之间的连接断开,这段代码会重新连接吗?
  • @MikeA 不。如果您想要一种可靠的方法来确保节目始终继续播放(即使出现错误),您还应该收听"error"以及XMLHttpRequest 可以发出的"abort" 事件,并相应地处理它们。请参阅here 了解更多信息。
  • 那么我应该将xhr.addEventListener("error", reqListener);xhr.addEventListener("abort", reqListener); 添加到我的checkQueue 函数中以在连接断开时建立重新连接吗?
【解决方案3】:

setInterval 只是在当前调用堆栈完成执行后将要运行的代码排队。这对某些事情很有用。

所以是的,它是异步的,因为它破坏了同步流程,但它实际上并不会同时/在单独的线程上执行。如果您的目标是后台处理,请查看 webworkers。

因此,无论服务器花费多少时间,它都会根据您的代码设置为 1000 每秒请求一次

【讨论】:

  • 这是否意味着 setTimeout 将在函数完成后 1 秒执行函数,而 setInterval 将执行而不考虑函数的结果?
  • 不管函数的结果如何,它都会执行。如果你不调用: clearInterval() 它不会停止,它会一次又一次地开始。
【解决方案4】:

是的,setInterval 和 setTimeout 是异步的,但是如果您想要阅读有关 Web 套接字的推送请求,则不是推送,而是拉取

【讨论】:

  • 我不能使用 websockets,因为我不使用框架。我的网站一直在重新加载。
猜你喜欢
  • 2021-06-29
  • 2020-06-29
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-15
  • 1970-01-01
  • 2020-06-22
相关资源
最近更新 更多