Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 当选项卡处于非活动状态时,保持JS/jQuery代码在Safari中工作_Javascript_Php_Jquery_Safari_Setinterval - Fatal编程技术网

Javascript 当选项卡处于非活动状态时,保持JS/jQuery代码在Safari中工作

Javascript 当选项卡处于非活动状态时,保持JS/jQuery代码在Safari中工作,javascript,php,jquery,safari,setinterval,Javascript,Php,Jquery,Safari,Setinterval,我有一个JS/jQuery代码,如下所示,在这个代码中,我希望在会话选项卡不活动时保持JS/jQuery代码工作 下面的代码在Google Chrome中非常好,但在Safari中不起作用 jQuery(document).ready(function ($) { let lastActivity = <?php echo time(); ?>; // Line A let now = <?php echo time(); ?>; let

我有一个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"
});
jQuery(文档).ready(函数($){
让lastActivity=;//行A
现在让我们=;
让logoutAfter=3600;//如果没有活动,页面将在1800秒后注销
让用户名=”;
let timer=setInterval(函数(){
现在++;
设delta=now-lastActivity;
console.log(delta);//行A
if(delta>logoutAfter){
清除间隔(计时器);
//是否执行关闭.php的AJAX请求
$.ajax({
url:“/control/admin.php”,
键入:“GET',//GET也很好
数据:{操作:'注销',用户名:},
成功:功能(数据){
window.location.href=“admin.php”;
},
错误:函数(jqXHR、textStatus、errorshown){
警报(文本状态);
}
});
}
},1000);//您可以用计算时差来替换计数器(计数秒)

let lastActivity = new Date();
let logoutAfter = 3600;
...
let delta = (new Date()).getTime() - lastActivity.getTime();
if (delta > logoutAfter) {
    ...
}
因此,即使在选项卡处于非活动状态时脚本本身被冻结,它也必须工作。当用户激活此选项卡时,将调用间隔处理程序。


此方法在打开多个选项卡时无法正常工作。如果用户打开新选项卡并开始使用它,则先前的选项卡将注销该用户,因为他在该选项卡中不活动。

为了克服这个问题,我建议使用ajax调用检查服务器的上一次活动时间,而不是只使用javascript
在Safari和Chrome上,非活动选项卡上的执行速度限制在1/s以内,但没有停止。关于Javascript在非活动选项卡上暂停或取消优先级,这里还有很多问题,其中一些包括解决方案:

可能做您正在尝试的事情的最佳选择是:

Web工作线程是Web内容在后台线程中运行脚本的一种简单方法。工作线程可以在不干扰用户界面的情况下执行任务

上面一个问题的答案中有一个答案

但是还有一个简单得多的选择,尽管考虑到您依赖它来注销用户,您应该评估它是否安全

我对代码的测试反映了
setInterval()
的速度被减慢,但没有停止。对我来说,Safari(v13.1,macOS 10.14.6)实际上并没有完全暂停Javascript,而是通过增加数量来减慢循环的执行。我通过打开开发控制台,并观察
console.log(delta)的输出看到了这一点
消息-它们会立即减速,先是每2秒运行一次,然后是4秒,依此类推,虽然有时会更快。但它们不会停止

该输出还提供了有关问题和解决方案的提示。控制台上显示的
delta
值并不表示自
lastActivity
以来的实时差异。它们只是递增的数字。如果在最后一个值出现10秒后控制台上出现
delta
值,则在逻辑上应该是
+10
,对吧?但事实并非如此,它只比这高一个

这就是这里的问题-代码不是计算真正的时间差,它只是计算循环的迭代次数:

let timer = setInterval(function () {
    now++;    // <-- problem
现在,即使迭代之间有10秒的暂停,
delta
将是加载页面以来经过的时间的真实度量。因此,即使用户切换到另一个选项卡,每次循环运行时,它都会正确跟踪时间,即使不是每秒都发生

那么这对你来说意味着什么呢

  • 根据您的报告,JS根本没有在非活动选项卡中运行。在这种情况下,选项卡可能会保持登录状态,超过用户应该注销的时间。但是,假设JS在您切换回选项卡时再次启动,循环的第一次迭代将正确计算时间elapsed。如果超过您的注销时间,您将注销。因此,即使该选项卡的登录时间超过其应有的时间,用户也无法使用它,因为一旦切换到该选项卡,他们将注销。请注意,“尽快”实际上是指“在1秒内加上AJAX查询成功注销用户所需的时间”

  • 在我的测试中,JS不会在非活动的Safari选项卡中停止,而是会立即变慢。在这种情况下,这意味着用户将自动在非活动选项卡上注销,尽管在他们应该注销的时间不正确。如果循环每8秒运行一次,这可能意味着用户将比他们应该拥有b的时间晚7秒注销甚至。如果迭代速度进一步减慢,延迟可能会更大。假设一旦用户切换回选项卡,JS会像正常情况一样重新启动,行为将与上述完全相同,在这种情况下,第一次迭代会将其注销

  • 编辑 这里是简化的、完整的代码,还有


    您好,您在这一行中做了更改。
    让lastActivity=;//行A
    ?我不允许在这一行中进行更改,因为它存储了最后一个活动。@flash Ok,让它像以前一样,-我想应该也可以。@flash忘了说,替换lastActivity.getTime()对于LastActivity,这是我尝试过的,但它在safari中仍然不起作用。让我知道我需要在fiddle中进行哪些更改才能使其起作用。在加载站点上的任何其他js之前,包含此脚本应该足够了:(我在此处发现:)很清楚,是桌面safari工作不正常还是移动(iPad/iPhone)Safari?@ChrisHaas的桌面Safari不是w
    // 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);
    
    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); 
    });