如何实施";功能超时“;在Javascript中—不仅仅是';设置超时';
如何在Javascript中实现a,而不是如何实施";功能超时“;在Javascript中—不仅仅是';设置超时';,javascript,timeout,Javascript,Timeout,如何在Javascript中实现a,而不是窗口.timeout,而是类似于会话超时或套接字超时——基本上是一个“函数超时” 系统中允许经过的指定时间段 在指定事件发生之前,除非另有规定 事件先发生;在任何一种情况下,当 任何一个事件都会发生 具体来说,我需要一个javascript观察计时器,它将观察函数的执行时间,如果达到或超过指定时间,则观察计时器将停止/通知执行函数 非常感谢您的帮助!非常感谢。我不完全清楚你在问什么,但我认为Javascript没有按照你想要的方式工作,因此无法完成。例如
窗口.timeout
,而是类似于会话超时
或套接字超时
——基本上是一个“函数超时
”
系统中允许经过的指定时间段
在指定事件发生之前,除非另有规定
事件先发生;在任何一种情况下,当
任何一个事件都会发生
具体来说,我需要一个javascript观察计时器
,它将观察函数的执行时间,如果达到或超过指定时间,则观察计时器将停止/通知执行函数
非常感谢您的帮助!非常感谢。我不完全清楚你在问什么,但我认为Javascript没有按照你想要的方式工作,因此无法完成。例如,常规函数调用不能一直持续到操作完成或某个时间段(以先到者为准)。这可以在javascript之外实现,并通过javascript公开(与同步ajax调用一样),但不能在具有常规函数的纯javascript中实现
与其他语言不同,Javascript是单线程的,因此当函数执行时,计时器永远不会执行(除了web workers,但它们的功能非常有限)。计时器只能在函数完成执行时执行。因此,您甚至不能在同步函数和计时器之间共享进度变量,因此计时器无法“检查”函数的进度 如果您的代码是完全独立的(没有访问任何全局变量,没有调用其他函数,也没有访问DOM),那么您可以在web worker中运行它(仅适用于较新的浏览器),并在主线程中使用计时器。当WebWorker代码完成时,它向主线程发送一条消息,其中包含它的结果。当主线程收到该消息时,它停止计时器。如果计时器在收到结果之前触发,它可能会杀死web工作者。但是,您的代码必须接受web工作人员的限制 Soemthing也可以通过异步操作完成(因为它们可以更好地处理Javascript的单线程特性),如下所示:
setTimeout()
作为超时时间启动计时器clearTimeout()
取消计时器并继续function loadImage(url, maxTime, data, fnSuccess, fnFail) {
var img = new Image();
var timer = setTimeout(function() {
timer = null;
fnFail(data, url);
}, maxTime);
img.onLoad = function() {
if (timer) {
clearTimeout(timer);
fnSuccess(data, img);
}
}
img.onAbort = img.onError = function() {
clearTimeout(timer);
fnFail(data, url);
}
img.src = url;
}
我不完全清楚你在问什么,但我认为Javascript没有按照你想要的方式工作,因此无法完成。例如,常规函数调用不能一直持续到操作完成或某个时间段(以先到者为准)。这可以在javascript之外实现,并通过javascript公开(与同步ajax调用一样),但不能在具有常规函数的纯javascript中实现
与其他语言不同,Javascript是单线程的,因此当函数执行时,计时器永远不会执行(除了web workers,但它们的功能非常有限)。计时器只能在函数完成执行时执行。因此,您甚至不能在同步函数和计时器之间共享进度变量,因此计时器无法“检查”函数的进度 如果您的代码是完全独立的(没有访问任何全局变量,没有调用其他函数,也没有访问DOM),那么您可以在web worker中运行它(仅适用于较新的浏览器),并在主线程中使用计时器。当WebWorker代码完成时,它向主线程发送一条消息,其中包含它的结果。当主线程收到该消息时,它停止计时器。如果计时器在收到结果之前触发,它可能会杀死web工作者。但是,您的代码必须接受web工作人员的限制 Soemthing也可以通过异步操作完成(因为它们可以更好地处理Javascript的单线程特性),如下所示:
setTimeout()
作为超时时间启动计时器clearTimeout()
取消计时器并继续function loadImage(url, maxTime, data, fnSuccess, fnFail) {
var img = new Image();
var timer = setTimeout(function() {
timer = null;
fnFail(data, url);
}, maxTime);
img.onLoad = function() {
if (timer) {
clearTimeout(timer);
fnSuccess(data, img);
}
}
img.onAbort = img.onError = function() {
clearTimeout(timer);
fnFail(data, url);
}
img.src = url;
}
只有使用一些核心技巧才能实现这一点。例如,如果您知道函数返回什么类型的变量(请注意,每个js函数都返回一些东西,默认值是
未定义的),您可以尝试以下操作:定义变量
var x = null;
并在单独的“线程”中运行测试:
最后运行函数:
x = myFunction(myArguments);
只有当您知道您的函数不返回任何值(即返回的值是未定义的)或它返回的值始终是“非false”,即未转换为false
语句(如0
,null
等)时,这才有效。您只能使用一些核心技巧来实现这一点。例如,如果您知道函数返回什么类型的变量(请注意,每个js函数都返回一些东西,默认值是未定义的),您可以尝试
execWithTimeout(function() {
if (Math.random() < 0.5) {
for(;;) {}
} else {
return 12;
}
}, 3000, function(err, result) {
if (err) {
console.log('Error: ' + err.message);
} else {
console.log('Result: ' + result);
}
});
function execWithTimeout(code, timeout, callback) {
var worker = new Worker('data:text/javascript;base64,' + btoa('self.postMessage((' + String(code) + '\n)());'));
var id = setTimeout(function() {
worker.terminate();
callback(new Error('Timeout'));
}, timeout);
worker.addEventListener('error', function(e) {
clearTimeout(id);
callback(e);
});
worker.addEventListener('message', function(e) {
clearTimeout(id);
callback(null, e.data);
});
}
export function callWithTimeout(func, timeout) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error("timeout")), timeout)
func().then(
response => resolve(response),
err => reject(new Error(err))
).finally(() => clearTimeout(timer))
})
}
export function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
const func1 = async () => {
// test: func completes in time
await sleep(100)
}
const func2 = async () => {
// test: func does not complete in time
await sleep(300)
}
const func3 = async () => {
// test: func throws exception before timeout
await sleep(100)
throw new Error("exception in func")
}
const func4 = async () => {
// test: func would have thrown exception but timeout occurred first
await sleep(300)
throw new Error("exception in func")
}
try {
await callWithTimeout(func, 200)
console.log("finished in time")
}
catch (err) {
console.log(err.message) // can be "timeout" or exception thrown by `func`
}