Javascript 我可以检测到挂起的JS函数并中止吗?
我正在开发一个工具,允许用户为查找和替换输入正则表达式,然后我的工具将执行该查找和替换并返回更改的文本。然而,我最近遇到了一种情况,find&replace只是冻结了,所以我决定最好用正则表达式匹配来检测问题,并在经过一定时间后中止 我四处查看了一下,发现我遇到的问题被称为“灾难性回溯”。知道这一点是很理想的,因为这样我就可以给出一个最小的工作示例,说明哪里出了问题,但是如果解决方案不可行,这并不理想,因为我无法控制用户的正则表达式输入(而且我也无法编写足够高级的正则表达式解析器来限制用户的正则表达式使用以排除类似情况) 因此,为了解决这个问题,我尝试使用承诺,如中所述。在本例中,我将“灾难性”匹配字符串设置为足够长的长度,以便在不完全破坏选项卡的情况下将选项卡挂起几秒钟。不同的电脑规格可能会看到不同的结果,但我不确定 只有一个提示:执行此代码可能会冻结当前选项卡。请确保在执行此代码时没有编写部分答案,因为这可能会导致工作损失。Javascript 我可以检测到挂起的JS函数并中止吗?,javascript,regex,error-handling,freeze,Javascript,Regex,Error Handling,Freeze,我正在开发一个工具,允许用户为查找和替换输入正则表达式,然后我的工具将执行该查找和替换并返回更改的文本。然而,我最近遇到了一种情况,find&replace只是冻结了,所以我决定最好用正则表达式匹配来检测问题,并在经过一定时间后中止 我四处查看了一下,发现我遇到的问题被称为“灾难性回溯”。知道这一点是很理想的,因为这样我就可以给出一个最小的工作示例,说明哪里出了问题,但是如果解决方案不可行,这并不理想,因为我无法控制用户的正则表达式输入(而且我也无法编写足够高级的正则表达式解析器来限制用户的正则
var PTest=函数(){
返回新承诺(功能(解决、拒绝){
setTimeout(函数(){
拒绝();
}, 100)
匹配(/(x+x++y/)
解决();
});
}
var myfunc=PTest();
myfunc.then(函数(){
控制台日志(“承诺已解决”);
}).catch(函数(){
控制台日志(“拒绝承诺”);
});代码>我建议使用Web Worker,因为它将在自己的沙箱中运行:
Web Worker是您需要包含在JavaScript中的自己的脚本,例如:
var worker = new Worker('/path/to/run-regex.js');
下面是未经测试的代码,但应该可以让您继续
您的run regex.js
是否与(可能长期运行的)regex匹配:
function regexMatch(str, regexStr, callback) {
let regex = new RegExp(regexStr);
let result = str.match(regex);
callback(result, '');
}
onmessage = function(e) {
let data = e.data;
switch (data.cmd) {
case 'match':
regexMatch(data.str, data.regex, function(result, err) {
postMessage({ cmd: data.cmd, result: result, err: err });
});
break;
case 'replace':
//regexMatch(data.str, data.regex, data.replace, function(result, err) {
// postMessage({ cmd: data.cmd, result: result, err: err });
//});
break;
default:
break;
postMessage({ err: 'Unknown command: ' + data.cmd });
}
}
在您自己的脚本中,加载Web Worker并添加事件侦听器:
if(window.Worker) {
const myWorker = new Worker('/path/to/run-regex.js');
myWorker.onmessage = function(e) {
let data = e.data;
if(data.err) {
// handle error
} else {
// handle match result using data.result;
}
}
function regexMatch(str, regex) {
let data = { cmd: 'match', str: str, regex: regex.toString() };
myWorker.postMessage(data);
}
regexMatch('xxxxxxxxxxxxxxxxxxxxxxxxx', /(x+x+)+y/);
} else {
console.log('Your browser does not support web workers.');
}
这样,当工作线程工作时,您的主JavaScript线程是非阻塞的
对于长时间运行的辅助程序,您可以向以下任一项添加代码:
- 使用
myWorker.terminate()
不正确地终止web worker,然后重新启动它--请参阅
- 或者,尝试从web worker范围内关闭()
——请参阅
我从未实现过这些,但可能会感兴趣。他们在该页面上给出的示例实际上与我的示例相同,唯一的例外是底部的6行被包装在异步函数中。这确实可能会有所不同,但即使修改示例以在其承诺范围内执行正则表达式匹配,也不会使脚本在指定的100ms后被拒绝。