簡體   English   中英

將JS/jQuery代碼保持在Safari中工作時

[英]Keep the JS/jQuery code working in Safari when the tab is not active

我有一個如下所示的 JS/jQuery 代碼,其中我想在 session 選項卡不活動時保持 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"
});

Z50DE9BC68C93DC32D8C7C7C90593471760Z在行Line A中的值不會遞增,當Tab不活動時,但在Google Chrome中起作用非常好。 在 Google Chrome 中,它按預期工作。

您可以用計算時差替換計數器(它計算秒數)。

let lastActivity = new Date();
let logoutAfter = 3600;
...
let delta = (new Date()).getTime() - lastActivity.getTime();
if (delta > logoutAfter) {
    ...
}

PS 因此,即使在選項卡處於非活動狀態時腳本本身被凍結,它也必須工作。 用戶激活此選項卡時將調用間隔處理程序。


此方法在打開多個選項卡時無法正常工作。 如果用戶打開新選項卡並開始在其中工作,則較早的選項卡將注銷用戶,因為他在該選項卡中不活動。

為了克服這個問題,我建議使用 ajax 調用而不是僅使用 javascript 來檢查服務器的最后活動時間。

根據這個非常徹底(但舊)的答案,在 Safari 和 Chrome 上,非活動選項卡上的setInterval()執行限制為最大 1/s - 但沒有停止。 這里還有很多關於 Javascript 在非活動選項卡上被暫停或取消優先級的問題,其中一些包括解決方案:

可能最好的選擇是使用 Web 工人

Web Worker 是 web 內容在后台線程中運行腳本的簡單方法。 工作線程可以在不干擾用戶界面的情況下執行任務。

在回答上述問題之一時,有一個如何做到這一點的例子

但是還有一個更簡單的選擇,盡管您應該評估它是否安全,因為您依賴它來注銷用戶。

我對您的代碼的測試反映了我之前鏈接到的問題,該問題描述了setInterval()正在減慢,但並未停止。 對我來說,Safari(v 13.1,macOS 10.14.6)實際上並沒有完全暫停 Javascript,而是通過增加數量來減慢循環的執行速度。 我通過打開開發控制台並查看console.log(delta)消息的 output 看到了這一點 - 它們會變慢,首先每 2 秒運行一次,然后每 4 秒運行一次,依此類推,盡管有時速度更快。 但他們並沒有停下來。

那 output 也給出了問題的提示和解決方案。 控制台上顯示的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也將是自頁面加載以來經過的時間的真實度量。 因此,即使用戶切換到另一個選項卡,每次循環運行時,它都會正確跟蹤時間,即使它不是每秒都發生。

那么這對你來說意味着什么?

  1. 根據您的報告,JS 根本沒有在非活動選項卡中運行。 在這種情況下,選項卡可能會停留在已登錄的 state 中,這已經超過了用戶應該注銷的時間。 但是,假設當您切換回選項卡時 JS 再次啟動,循環的第一次迭代將正確計算經過的時間。 如果它大於您的注銷期限,您將被注銷。 因此,即使選項卡的登錄時間超過了應有的時間,用戶也無法使用它,因為一旦切換到它,他們就會被注銷。 請注意,“盡快”實際上是指“在 1 秒內加上 AJAX 查詢成功注銷用戶所需的時間”。

  2. 在我的測試中,JS 不會在非活動的 Safari 選項卡中停止,而是會減慢速度。 在這種情況下,這意味着用戶將在非活動選項卡上自動注銷,盡管不是在他們應該在的時間。 如果循環每 8 秒運行一次,則可能意味着用戶將在 7 秒后注銷。 如果迭代速度更慢,延遲可能會更大。 假設一旦用戶切換回選項卡,JS 就會再次正常啟動,行為將與上述完全相同,在這種情況下,第一次迭代會將它們注銷。

編輯

這是簡化的完整代碼,以及顯示它正在運行和工作的 JSFiddle

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); 
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM