setTimeout被连续的AJAX请求阻止了吗? [英] setTimeout blocked by continuous AJAX requests?

查看:319
本文介绍了setTimeout被连续的AJAX请求阻止了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用setTimeout通知后端保持会话活动的Web应用程序上修复了一个问题。除了以下情况之外,这在所有场景中均可正常工作:

Im fixing an issue on a web application that uses setTimeout to inform the back end to keep the session alive. This works as expected in all scenarios except for the following:

当发生背靠背同步AJAX帖子时,setTimeout不会触发。

The setTimeout is not triggering while there are back to back sync AJAX posts happening.

据我所知,由于 JavaScript是单线程的,因此setTimeout触发可能会有延迟并且必须等待一个任务完成。

I understand that there can be a delay for the setTimeout firing as JavaScript is single-threaded and has to wait for one task to complete.

我的问题是:为什么setTimeout根本没有触发?为什么它在所有AJAX请求结束时被解雇而不是在两者之间?

My question is: Why is the setTimeout not firing at all? Why is it fired at the end of all the AJAX requests and not in between?

这是我的keepAlive函数

This is my keepAlive function

function keepAlive() {
    var img = new Image(1, 1);
    img.src = "google.com" + '?' + new Date();

    timer = setTimeout(function () {
        keepAlive();
    }, 10000);
}

我创建了一个快速而又脏的演示我在jsfiddle的问题。

I have created a quick and dirty demo of my problem in jsfiddle.

提前致谢!

推荐答案


当有背靠背同步AJAX帖子发生时,setTimeout没有触发。

The setTimeout is not triggering while there are back to back sync AJAX posts happening.

...

我的问题是:为什么setTimeout根本没有触发?为什么它会在所有AJAX请求结束时被解雇而不是在两者之间?

My question is: Why is the setTimeout not firing at all? Why is it fired at the end of all the AJAX requests and not in between?

因为它们是同步请求。这是不使用同步请求的众多原因之一;改为使用异步请求。

Because they're synchronous requests. This is one of the many reasons not to use synchronous requests; use asynchronous requests instead.

当ajax请求是同步的时,它就像一个函数调用:它占用主UI线程。所以:

When an ajax request is synchronous, it's just like a function call: It ties up the main UI thread. So:

doThisSyncRequest();
doThatSyncRequest();
doTheOtherSyncRequest();

上面没有任何一点,线程会回到空闲状态并查看其排队的工作,所以排队的 setTimeout 回调无法运行。

At no point in the above does the thread go back to the idle state and look at its queued work, and so the setTimeout callback that's queued can't run.

主UI线程通过任务队列工作:

The main UI thread works through a task queue:


  1. 任务队列为空时空闲

  1. Idle while the task queue is empty

当某些事情发生时(一般意义上的事件,包括计时器到期,添加新代码等),浏览器将一个任务与关联的JavaScript代码排队,以便主UI线程获取

When something happens (an "event" in the general sense, including a timer expiring, new code being added, etc.), the browser queues a task with associated JavaScript code for the main UI thread to pick up

当主UI线程选择任务时,它会运行相关代码不间断

When the main UI thread picks up a task, it runs the associated code uninterrupted

如果在代码运行时发生其他事情,浏览器会为这些事情排队任务并在队列中等待

If other things happen while that code is running, the browser queues tasks for those things and they wait in the queue

当主UI线程时完成为一个任务运行代码,它从队列中获取下一个任务(如果有的话)或者回到空闲状态

When the main UI thread finishes running the code for one task, it picks up the next task from the queue (if any) or goes back to idling

由于同步请求会阻止线程,因此当它们运行时它会在#3中停留,并且其他任何事件都会排队。

Since synchronous requests hold up the thread, it stays stuck in #3 while they're running, and anything else queues up.

当您使用异步请求时,启动它们的JavaScript代码在运行时不会被阻止;相反,代码流继续并完成,主UI线程可以继续处理后续任务。最终异步请求的状态发生了变化(例如,它完成),它将任务排队以调用就绪状态更改回调。

When you use asynchronous requests, the JavaScript code that starts them doesn't get held up while they're running; instead, the code flow continues and finishes, and the main UI thread can continue processing subsequent tasks. Eventually the async request's state changes (for instance, it completes), which queues a task to call the ready state change callback.

我建议使用异步请求,多个原因,包括同步请求导致糟糕的用户体验,因为UI在请求期间锁定。但只是为了完整性,你确实有另一种选择:你可以移动那个背景ajax调用以使会话保持活跃状态​​ web worker 线程代替。然后,由于它在不同的线程上运行,因此主UI线程上的同步ajax调用不会阻止它运行。我不是推荐这个(我建议使用异步请求),只是将其标记为选项。所有现代桌面浏览器(但不是IE9及更早版本)都支持网络工作者 ,移动支持正在改进,并且它很容易被特征检测它们是否受支持并且如果没有则回退到使用主UI线程。但实际上,异步请求是可行的方法。

I would recommend using asynchronous requests, for multiple reasons, including that synchronous requests make for a poor user experience because the UI locks up during the request. But just for completeness, you do have an alternative: You could move that background ajax call to keep the session alive into a web worker thread instead. Then, since it's running on a different thread, synchronous ajax calls on the main UI thread don't prevent it from running. I'm not recommending this (I recommend using async requests instead), just flagging it up as an option. Web workers are supported in all modern desktop browsers (but not IE9 and earlier), mobile support is improving, and it's easy to feature-detect whether they're supported and fall back to using the main UI thread if not. But really, async requests are the way to go.

这篇关于setTimeout被连续的AJAX请求阻止了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆