如何在Javascript中实现timeout,而不是window.timeout
,而是session timeout
或socket timeout
- 基本上 - “function timeout
”
系统中允许的指定时间段 在指定事件发生之前,除非指定另一个事件 事件先发生;在任何一种情况下,期间终止时 任何一个事件发生。
具体来说,我想要一个javascript observing timer
来观察一个函数的执行时间,如果达到或超过指定的时间,那么observing timer
将停止/通知执行函数。
非常感谢任何帮助!非常感谢。
答案 0 :(得分:12)
我并不完全清楚你在问什么,但我认为Javascript不能按你想要的方式工作,所以无法完成。例如,无法执行常规函数调用,直到操作完成或持续一定时间(以先到者为准)。这可以在javascript之外实现并通过javascript公开(就像使用同步ajax调用一样),但不能在具有常规函数的纯javascript中完成。
与其他语言不同,Javascript是单线程的,因此当一个函数执行时,计时器将永远不会执行(除了Web工作者,但是他们可以做的非常非常有限)。定时器只能在函数完成执行时执行。因此,您甚至无法在同步函数和计时器之间共享进度变量,因此计时器无法“检查”函数的进度。
如果你的代码是完全独立的(没有访问你的任何全局变量,没有调用你的其他函数并且无论如何也没有访问过DOM),那么你可以在web-worker中运行它(仅在较新的浏览器中可用)并在主线程中使用计时器。当web-worker代码完成时,它会向主线程发送一条消息及其结果。当主线程收到该消息时,它会停止计时器。如果计时器在接收结果之前触发,则可以终止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;
}
答案 1 :(得分:2)
您可以在Web worker中执行代码。然后,您仍然可以在代码运行时处理超时事件。 Web工作人员完成其工作后,您可以取消超时。一旦发生超时,您就可以终止Web工作者。
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);
});
}
答案 2 :(得分:1)
你只能使用一些硬核技巧来达到这个目的。例如,如果你知道你的函数返回什么类型的变量(注意每个 js函数返回一些东西,默认是undefined
)你可以尝试这样的东西:define variable
var x = null;
并在单独的“线程”中运行测试:
function test(){
if (x || x == undefined)
console.log("Cool, my function finished the job!");
else
console.log("Ehh, still far from finishing!");
}
setTimeout(test, 10000);
最后运行功能:
x = myFunction(myArguments);
仅当您知道函数未返回任何值(即返回值为undefined
)或返回的值始终为“not false”时才有效,即未转换为{{1 }}语句(如false
,0
等)。
答案 3 :(得分:0)
我意识到这是一个古老的问题/话题,但这也许会对其他人有所帮助。
这是一个通用的callWithTimeout
,您可以await
:
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`
}
答案 4 :(得分:0)
My question 已被标记为该帖子的副本,所以我想我会回答它,即使原来的帖子已经九年了。
我花了一些时间来理解 Javascript 是单线程意味着什么(我仍然不确定我是否 100% 理解了事情)但这里是我如何使用 Promises 和回调。它主要基于 this tutorial。
首先,我们定义一个 timeout
函数来包装 Promises:
const timeout = (prom, time, exception) => {
let timer;
return Promise.race([
prom,
new Promise((_r, rej) => timer = setTimeout(rej, time, exception))
]).finally(() => clearTimeout(timer));
}
这是我想超时的承诺:
const someLongRunningFunction = async () => {
...
return ...;
}
最后,我是这样使用的。
const TIMEOUT = 2000;
const timeoutError = Symbol();
var value = "some default value";
try {
value = await timeout(someLongRunningFunction(), TIMEOUT, timeoutError);
}
catch(e) {
if (e === timeoutError) {
console.log("Timeout");
}
else {
console.log("Error: " + e);
}
}
finally {
return callback(value);
}
这将调用 callback
函数,返回值为 someLongRunningFunction
或超时时的默认值。您可以修改它以不同方式处理超时(例如抛出错误)。
答案 5 :(得分:-1)
在observing timer
和executing function
之间共享变量。
使用observing timer
或window.setTimeout
实施window.setInterval
。当observing timer
执行时,它会将退出值设置为共享变量。
executing function
不断检查变量值..如果指定了 exit ,则返回。