停止浏览器上长时间运行的javascript函数



我的问题有两部分

  1. 如果函数运行超过200ms,我想终止它并返回默认值。我试着用Promise.rese的概念进行实验,但没有产生想要的结果

  2. 我想确定该函数是否有一个无限循环,类似于当有人在不冻结浏览器或CPU 过载的情况下使用无限循环时JSFiddle或Codepen如何退出

有可能吗

是的,你可以做到,这是我作为概念验证编写的通用脚本。它动态地创建一个web工作程序,并以与其他语言具有线程相同的方式使用它。然而,如果您只是想终止一个活动的XHR或Fetch调用,那么有一些内置的方法可以做到这一点。

/**
* Run some code in it's own thread
* @params - Any parameters you want to be passed into the thread
* @param - The last parameter must be a function that will run in it's own thread
* @returns - An promise-like object with a `then`, `catch`, and `abort` method
*/
function Thread() {
var worker;
const promise = new Promise((resolve, reject) => {
var args = Array.from(arguments);
var func = args.pop();
if (typeof func !== "function") throw new Error("Invalid function");
var fstr = func.toString();
var mainBody = fstr.substring(fstr.indexOf("{") + 1, fstr.lastIndexOf("}"));
var paramNames = fstr.substring(fstr.indexOf("(") + 1, fstr.indexOf(")")).split(",").map(p => p.trim());
var doneFunct = paramNames.pop();
if (paramNames.length !== args.length) throw new Error("Invalid number of arguments.");
var workerStr = `var ${doneFunct} = function(){
var args = Array.from(arguments);
postMessage(args);
};
self.onmessage = function(d){
var [${paramNames.join(", ")}] = d.data;
${mainBody}
};`;
var blob = new Blob([workerStr], {
type: 'application/javascript'
});
worker = new Worker(URL.createObjectURL(blob));
worker.onerror = reject;
worker.onmessage = (d) => {
resolve(...d.data);
worker.terminate();
};
worker.postMessage(args);
});
return {
then: (...params)=>promise.then(...params),
catch: (...params)=>promise.catch(...params),
abort: ()=>worker.terminate()
}
}
////////////////////////
//// EXAMPLE USAGE /////
////////////////////////
// the thread will take 2 seconds to execute
// and then log the result
var myThread = new Thread("this is a message", 2, function(message, delaySeconds, exit) {
setTimeout(() => {
exit(message.split('').reverse().join(''));
}, delaySeconds * 1000);
});
myThread.then(result => console.log(result));
// the thread will take 2 seconds to execute
// but we will cancel it after one second
var myThread = new Thread("this is a message", 2, function(message, delaySeconds, exit) {
setTimeout(() => {
exit(message.split('').reverse().join(''));
}, delaySeconds * 1000);
});
setTimeout(()=>{
myThread.abort();
}, 1000);

如果您有权访问该函数,您可以在循环中添加一个时间检查,该检查会运行很长时间,并在达到时间限制时返回(最简单、最兼容的方式(。

如果您不知道该函数在做什么或无法修改它,可以尝试将它封装在Web工作程序中。如果你在worker内部启动长时间运行的js,那么当它到达超时时,你可以.terminate((它

此外,如果不执行,就不可能确定某个东西是否包含无限循环

最新更新