这是一件很奇怪的事。我们有一个 Laravel 网站,在该网站上,我们为每个用户设置了一个计时器,他们在启动前有 15 分钟处于非事件状态。
我们通过一个位于 React 组件页面上的计时器来实现这一点,它可以按照我们想要的方式工作,但现在我们遇到了一个新问题:如果用户登录并关闭笔记本电脑的盖子,网站应该启动他们.银行这样做,学校和大学这样做,政府网站也这样做。所以这是可能的,只是不确定如何。
我们确实使用网络套接字,使用 laravel-websockets图书馆和 echo 。我希望看到的是:
有些人在其他类似的问题中提出了建议:
最流行的似乎是使用网络套接字,监听用户断开连接然后启动它们,这很好,但是你如何向暂停的浏览器发送请求然后启动它们?
我找到了 requestIdleCallback()但同样,如果我已经在网站上有一个心跳计时器,我认为这不是我想要的。它也不适用于所有浏览器。
我对如何做到这一点非常迷茫,我可以举的例子是:
登录您的银行,让您的计算机进入休眠状态,等待 15-20 分钟,唤醒计算机,登录并看到您的银行现在在登录屏幕上显示您。 这就是我想要的 .但我不知道如何做到这一点。
您无法从后端向“休眠”浏览器发送事件,虽然这必须是后端解决方案,但您如何更新前端,以便它们在重新唤醒笔记本电脑时显示在注销屏幕上还是电脑?
最佳答案
更新
关于 WebSocket 请求,我假设您使用的是 Laravel WebSockets与 pusher
. Pusher.io 不支持超时 ,您可以阅读这篇支持文章 "Do you plan to add a connection timeout feature to the Channels pusher-js client library?" .如果您启用 Laravel Debug模式( APP_DEBUG=true
内 .env
)并开始 laravel-websockets
,您可以测试它从终端( php artisan websockets:serve
),所以你可以看到输出日志事件。如果您尝试合上笔记本电脑盖或将计算机设置为休眠模式( sleep ),您将不会看到有关此事件的任何消息。你不能用 pusher
做到这一点协议(protocol)。有 member_removed
Presence event ,但这仅在您关闭选项卡或注销时触发。当然,您可以将客户端自定义事件触发到在线状态 channel ,但要做到这一点,您还需要在客户端设置一个计时器,并且您必须为 laravel-websockets
创建一个服务提供者。服务器喜欢这个 github 问题 "Exist a way to implement webhooks?" .
Some people have suggested in other similar questions:
...
- To have a timer running on the front end (we do, it just stops when you close the laptop lid)
发生这种情况是因为客户端计时器在休眠时停止执行,因此它们从之前的位置继续。但是如果你使用日期变量来保存时间 ,当计算机进入休眠状态时,该变量不会更新,因此 通过检查日期变量 ,您就会知道它何时从 sleep 中醒来这与当前时间相比会有显着差异,并且会大于计时器间隔。
在客户端实现时间逻辑
您还可以看到此相关 Q/A 的实现:Can any desktop browsers detect when the computer resumes from sleep?
您可以在客户端设置一个计时器,每分钟运行一次。 我们不会依赖定时器间隔 ,但该计时器将检查 外部范围日期变量 如果自上次计时器以来的时间跨度大于
15
分钟;如果是,那么这意味着 浏览器/JS 因某种原因停止执行 ,可能是设备休眠( sleep ),然后您将用户重定向到注销路由。示例JS客户端代码:
// Set a variable to check previous time
let clientSession = new Date;
// Setup the client session checking timer
let clientSessionTimer = setInterval(() => {
const now = new Date;
// Get how many seconds have passed since last check
const secondsSpan = (now - clientSession) / 1000;
// If the 1 minute timer has exceeded 15 minutes trigger logout and clear timer
if (secondsSpan > (60 * 15)) {
// For some reason JS halted execution, so we'll proceed with logging out
clearInterval(clientSessionTimer);
window.location.href = '/logout/session'
} else {
// The timer runs as it should, update the clientSession time
clientSession = now;
}
}, 1000 * 60);
你可以检查这个简单的例子,但使用 1
第二个计时器 15
秒登出这里。最好在关闭盖子的笔记本电脑上测试它,然后在每两分钟 15 秒后再次打开它,因为如果你有很多程序正在运行,计算机需要一些时间来保存内存状态,以便完成休眠模式并停止执行。Web Worker 示例
您甚至可以使用 Web Workers API设置一个网络 worker 更安全:
页面JS代码:
const logoutWorker = new Worker('logoutWorker.js');
logoutWorker.onmessage = function (ev) {
if (ev && ev.data === 'wakeup') {
logoutWorker.terminate();
// window.location.href = '/logout/session'
} else {
// The timer runs as it should, nothing to do
}
}
网络 worker logoutWorker.js
代码:let clientSession = new Date();
let clientSessionTimer = setInterval(() => {
const now = new Date;
const secondsSpan = (now - clientSession) / 1000;
if (secondsSpan > 15) {
postMessage('wakeup'); // Send a message wakeup to the worker page
clearInterval(clientSessionTimer); // Clear the timer
} else {
clientSession = now; // Update the clientSession timer variable
postMessage('update'); // And post a message to the page ONLY IF needed
}
}, 1000);
您还可以使用相同的 15
检查 Web Worker 示例。秒计时器 here .
关于javascript - 当用户将计算机置于 sleep 状态时,将用户从网站上注销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60624694/