我正在开发一个在远程计算机上连续运行并且需要更新的用户脚本。
但是,当脚本自动更新时,它需要重新加载页面来应用更新,所以我的脚本也在尝试预测更新何时发生,以便之后可以刷新页面。
事实证明这很困难:即使我将时间段设置为至少六个小时,脚本通常会在上次更新后更新七个或更长时间。
那么 uodates 的逻辑是如何工作的呢?是否有一个钩子或回调可以用来在更新后重新加载页面,以便应用它?或者您还有其他一些技巧可以更准确地预测脚本更新的时间吗?
这是我目前用来执行此操作的逻辑:
function monitorScriptUpdates() {
informUserIfScriptUpdated();
var updateTimerSet = false;
var timer = setInterval(() => {
if (updateTimerSet) {
clearInterval(timer);
} else {
checkForUpdates();
}
}, 60000);
function checkForUpdates() {
getNewestScriptVersion().then((newestVersion) => {
const actualScriptVersion = GM_info.script.version;
if (actualScriptVersion >= newestVersion) {
return;
}
const currentTimeInMs = Date.now();
const scriptLastUpdatedMs = GM_info.script.lastModified;
const msSinceTheLastUpdate = currentTimeInMs - scriptLastUpdatedMs;
const sixHoursInMs = 21600000;
const fiftyMinutesBuffer = 3000000;
updateTimerSet = true;
if (localStorage.getItem('updateAttempted')) {
localStorage.removeItem('updateAttempted');
console.log('Automatic update failed, possibly because the update period is set to more than 6 hours! Disabling update check.');
return;
}
const timeUntilUpdateIsAvailable = (sixHoursInMs - (msSinceTheLastUpdate % sixHoursInMs)) + fiftyMinutesBuffer;
console.log('New script version detected! Automatic update will be attempted on ' + new Date(Date.now() + timeUntilUpdateIsAvailable));
setTimeout(() => {
console.log('Update should be available if the update period is set to 6 hours. Reloading...');
localStorage.setItem('updateAttempted', true);
location.reload();
}, timeUntilUpdateIsAvailable);
});
}
function informUserIfScriptUpdated() {
var lastRecordedVersion = localStorage.getItem('scriptVersion');
var actualScriptVersion = GM_info.script.version;
if (lastRecordedVersion && lastRecordedVersion != actualScriptVersion) {
localStorage.removeItem('updateAttempted');
console.log('Script updated successfully from version ' + lastRecordedVersion + ' to version ' + actualScriptVersion);
}
localStorage.setItem('scriptVersion', actualScriptVersion);
}
}
谢谢, 杜桑
setTimeout
和setInterval
极其不可靠,因为浏览器为了节省资源会暂停非活动选项卡的JS执行。
因此,您应该使用
setTimeout
,而不是使用 Date.Now()
,检查当前时间,然后根据需要进行更新。像这样:
setTimeout(() => {
console.log('Update should be available if the update period is set to 6 hours. Reloading...');
localStorage.setItem('updateAttempted', true);
location.reload();
}, timeUntilUpdateIsAvailable);
应替换为:
const nextUpdateTime = Date.now() + timeUntilUpdateIsAvailable;
setInterval(()=>{
if (Date.now() >= nextUpdateTime){
console.log('Update should be available if the update period is set to 6 hours. Reloading...');
localStorage.setItem('updateAttempted', true);
location.reload();
}
}, 600000); // Every 10 minutes, we check if the time expired.