一)程序步骤
1、js 写一个定时请求后端(php),后端接收到请求到,把当前时间戳写入文件
2、php 阻塞,这里我写的是 30 秒,也就是 sleep(30)
3、获取当前时间和文件里的时间作比较,如果时间间隔为 30 秒,则表示前端已经没有请求了,视为用户关闭了所有网站相关的 tab
二)实现原理
首先,每一个请求过来时,都会立即更新文件里的时间戳,然后阻塞程序 30 秒;
那么,如果我设置的前端的定时请求为 17 秒,第二请求过来的时候,其实第一个请求还没处理完(因为阻塞了 30 秒);
当第一个请求阻塞结束,往下执行时,文件里的时间戳已经被第一个请求修改了,这时再用当前时间 减 文件里的时间戳,间隔肯定不是 30 秒了;
反之,如果减出来的间隔为 30 秒,则表示,文件时间戳没有被修改,也就是没有下一个请求了,视为用户关闭了所以网站链接,这时就可以做登出之类的日志记录了
三)部分代码
js:
function test(url){ var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function(){ if(xmlhttp.readyState==4){ if(xmlhttp.status==200){ // console.log(xmlhttp.responseText); } } } xmlhttp.open("GET", url, true); xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xmlhttp.send(null); }
window.setMyInterval = function(func, interval){ var nexttime = interval; var start = new Date().getTime(); var now = null; var toffset = 0; var i = 0; var timer = null; var gogogo = function(){ timer = window.setTimeout(function(){ i++; now = new Date().getTime(); toffset = now - (start + i * interval); nexttime = interval - toffset; func(); gogogo(); }, nexttime); }; // 先立即执行一次 func(); // 启动迭代器 gogogo(); return timer; }
var i = 0;
window.setMyInterval(function(){
test('test'+ ((i%2)+1) +'.php');
i++;
}, 17000);
test('test.php');
php:
test.php(实际使用时用 redis 会更好)
<?php file_put_contents('user1_time.txt', time()); sleep(3); $t1 = file_get_contents('user1_time.txt'); $now = time(); if($now - $t1 == 3){ error_log("SUCCESS", 3, "debug.txt"); unlink('user1_time.txt'); } ?>