亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當選項卡未激活時,保持 JS/jQuery 代碼在 Safari 中正常工作

當選項卡未激活時,保持 JS/jQuery 代碼在 Safari 中正常工作

PHP
慕仙森 2023-08-19 10:22:07
我有一個 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"});Line A當選項卡未處于活動狀態時,Safari 中的值不會增加,但在 Google Chrome 中卻可以正常工作。在 Google Chrome 中,它按預期工作。
查看完整描述

3 回答

?
縹緲止盈

TA貢獻2041條經驗 獲得超4個贊

這就是這里的問題 - 代碼不計算真實的時間差,它只是計算循環的迭代次數:

let timer = setInterval(function () {

? ? now++;? ? // <-- problem

僅當每秒運行一次時,此代碼才能正確設置now為當前時間。但我們知道,當選項卡處于非活動狀態時,它不會。在這種情況下,它只是計算循環運行的次數,與實際經過的時間無關。setInterval()


為了解決這個問題,我們必須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 根本沒有在非活動選項卡中運行。在這種情況下,選項卡可能會一直處于登錄狀態,遠遠超出了用戶應該注銷的時間。但是,假設當您切換回選項卡時 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);?

});


查看完整回答
反對 回復 2023-08-19
?
慕斯王

TA貢獻1864條經驗 獲得超2個贊

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

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

查看完整回答
反對 回復 2023-08-19
?
瀟瀟雨雨

TA貢獻1833條經驗 獲得超4個贊

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


let lastActivity = new Date();

let logoutAfter = 3600;

...

let delta = (new Date()).getTime() - lastActivity.getTime();

if (delta > logoutAfter) {

    ...

}

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


查看完整回答
反對 回復 2023-08-19
  • 3 回答
  • 0 關注
  • 195 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號