我有一个JS/jQuery代码,如下所示,在这个代码中,我希望在会话选项卡不活动时保持JS/jQuery代码工作。
下面的代码在Google Chrome中非常好,但在Safari中不起作用。
jQuery(document).ready(function ($) {
let lastActivity = <?php echo time(); ?>; // Line A
let now = <?php echo time(); ?>;
let logoutAfter = 3600; // page will logout after 1800 seconds if there is no activity
let userName = "<?php echo $_SESSION['user_name']; ?>";
let timer = setInterval(function () {
now++;
let delta = now - lastActivity;
console.log(delta); // Line A
if (delta > logoutAfter) {
clearInterval(timer);
//DO AJAX REQUEST TO close.php
$.ajax({
url: "/control/admin.php",
type: 'GET', // GET also fine
data: {action: 'logout', user_name: userName},
success: function (data) {
window.location.href = "admin.php";
},
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus);
}
});
}
}, 1000); //<-- you can increase it( till <= logoutAfter ) for better performance as suggested by @"Space Coding"
});
在Safari中,当选项卡处于非活动状态时,行A
上的值不会增加,但在Google Chrome中,它工作得非常好。在Google Chrome中,它可以按预期工作。
根据这个非常彻底(但很旧)的答案,setInterval()
在非活动选项卡上的执行速度限制为1/s,在Safari和Chrome上都是如此,但没有停止。这里还有很多关于Javascript在非活动选项卡上暂停或取消优先级的问题,其中一些包括解决方案:
您尝试的最佳选择可能是使用Web workers:
Web Worker是Web内容在后台线程中运行脚本的一种简单方法。工作线程可以在不干扰用户界面的情况下执行任务。
在回答上述一个问题时,有一个例子说明了如何做到这一点。
但是还有一个更简单的选项,尽管考虑到您依赖于此来注销用户,您应该评估它是否安全。
我对代码的测试反映了我之前链接到的问题,该问题描述了setInterval()
正在变慢,但没有停止。对我来说,Safari(v13.1,Macos10.14.6)实际上并没有完全暂停Javascript,而是通过增加数量来减慢循环的执行。我通过打开dev控制台并观察console.log(delta)
消息的输出看到了这一点——它们会立即减慢速度,首先只运行2秒,然后运行4秒,以此类推,尽管有时会更快。但他们并没有停止。
该输出还提供了有关问题和解决方案的提示。控制台上显示的delta
值并不代表自lastActivity
以来的实时差异。他们只是在增加数字。如果在最后一个值出现10秒后控制台上出现delta
值,则逻辑上应该是10
,对吗?但事实并非如此,它只是高了一点。
这就是这里的问题-代码不是计算真正的时间差,它只是计算循环的迭代次数:
let timer = setInterval(function () {
now++; // <-- problem
只有当setInterval()每秒钟运行一次时,这段代码才能正确地将now
设置为当前时间。但是我们知道,当选项卡处于非活动状态时,它不会。在这种情况下,它只是计算循环运行的次数,与实际时间无关。
为了解决这个问题,我们必须根据实时确定now
。为了做到这一点,让我们切换到使用JS来计算我们的时间戳(PHP在页面加载时只呈现一次,所以如果你在循环中使用它,它只会保持在初始值不变):
// Note that JS gives us milliseconds, not seconds
let lastActivity = Date.now();
let now = Date.now();
let logoutAfter = 3600 * 1000;
let timer = setInterval(function () {
// PHP won't work, time() is rendered only once, on page load
// let now = <?php echo time(); ?>;
now = Date.now();
let delta = now - lastActivity;
console.log('New timer loop, now:', now, '; delta:', delta);
现在,即使迭代之间有10秒的停顿,delta
将是自页面加载以来所经过的时间的真实度量。因此,即使用户切换到另一个选项卡,每次循环运行时,它都会正确跟踪时间,即使它不是每秒钟都发生。
那么这对你来说意味着什么呢?
>
根据您的报告,JS在非活动选项卡中根本没有运行。在这种情况下,选项卡可能会停留在已登录状态,超过了用户应该注销的时间。但是,假设在切换回选项卡时JS再次启动,则循环的第一次迭代将正确计算经过的时间。如果超过您的注销期限,您将被注销。因此,即使该选项卡的登录时间超过了应有的时间,用户也无法使用它,因为一旦他们切换到该选项卡,就会注销。请注意,“尽快”实际上意味着“在1秒内加上AJAX查询成功注销用户所需的时间”。
在我的测试中,JS不会在非活动的Safari选项卡中停止,而是会立即减慢速度。在这种情况下,这将意味着用户将在非活动选项卡上自动注销,尽管在应该注销的时间并不正确。如果循环每8秒运行一次,这可能意味着用户将比应该的时间晚7秒注销。如果迭代速度更慢,延迟可能会更大。假设一旦用户切换回选项卡,JS就会像正常一样重新启动,行为将与上述完全相同,在这种情况下,第一次迭代将把它们注销。
这里是简化的、完整的代码,以及一个JSFIDLE,显示了它的运行和工作。
jQuery(document).ready(function($) {
let lastActivity = Date.now();
let now = Date.now();
let logoutAfter = 3600 * 1000;
let timer = setInterval(function() {
now = Date.now();
let delta = now - lastActivity;
console.log('New timer loop, now:', now, '; delta:', delta);
if (delta > logoutAfter) {
alert('logout!');
}
}, 1000);
});
您可以用计算时差来替换计数器(计数秒)。
let lastActivity = new Date();
let logoutAfter = 3600;
...
let delta = (new Date()).getTime() - lastActivity.getTime();
if (delta > logoutAfter) {
...
}
P. S.因此,它必须工作,即使脚本本身是冻结时,制表符是不活动的。当用户激活此选项卡时,将调用间隔处理程序。
问题内容: 我正在使用jQuery标签,并且其中一个标签中的内容是通过AJAX调用检索的。但是我不希望在单击选项卡(使其处于活动状态)之前触发呼叫,因为用户可能不一定会单击它。最好的方法是什么? jQuery UI为选项卡提供了和事件,但是当选择或显示 任何 选项卡时,这些事件就会触发,而不仅仅是特定的选项卡(据我所知)。 我还尝试将事件分配给特定标签的ID: 但这似乎没有任何作用,并且永远不会触
问题内容: 是否有可能使MySQL中的行处于非活动状态?因此,该行不再用于查询结果吗?我的客户希望保留删除的成员在数据库中的存在,但是我不想编辑所有查询以检查该成员是否被删除。 还是有一种简单的方法将整个行数据移动到另一个“非活动”表中? 问题答案: 您可以重命名当前表,在其中创建“ deleted”列,然后创建一个与当前表同名的视图,并选择“ deleted = 0”。这样,您不必更改所有查询。
我正在Android上使用Firebase云消息。 当应用程序位于前台时,我可以成功接收通知和数据消息 文档说明,如果在应用程序处于后台时收到通知消息,则Firebase将代表应用程序向系统托盘发送通知。这对我不起作用 如果发送了数据消息且应用程序位于后台,则会成功调用onMessageReceived方法 最麻烦的情况是,我强制停止应用程序,然后尝试发送通知或数据消息。在这种情况下,不会调用on
那么我应该做些什么来实现这个目标呢?如有任何帮助/线索,请提前感谢
问题内容: 从MDN for NodeList: 在某些情况下,NodeList是一个实时集合,这意味着DOM中的更改会反映在集合中。例如,Node.childNodes处于活动状态: 在其他情况下,NodeList是静态集合,这意味着DOM中的任何后续更改都不会影响集合的内容。document.querySelectorAll返回一个静态NodeList。 所以....有点烦!是否有任何关于哪些
我如何知道我的系统中哪个选项卡处于活动状态 public View oncreate View(LayoutInflater inflater,ViewGroup容器,Bundle savedInstanceState)函数??? 以下代码仅适用于拳头导航,但之后在每个选项卡中,它都会显示最后一个布局。 我认为问题出在< code>onCreateView函数中,我无法获取活动选项卡的位置。 我怎