Javascript 使用setTimeout中断长时间运行的函数以允许事件处理
我必须找到一种方法来实现一个函数,该函数接受一个输入数字,并返回/显示最接近的较小素数或输入本身(如果它是素数) 然而,输入可能是一个非常大的数字,在这种情况下,内部函数会阻塞事件循环,我必须确保浏览器能够在计算期间处理事件 我的实现如下所示:Javascript 使用setTimeout中断长时间运行的函数以允许事件处理,javascript,event-loop,Javascript,Event Loop,我必须找到一种方法来实现一个函数,该函数接受一个输入数字,并返回/显示最接近的较小素数或输入本身(如果它是素数) 然而,输入可能是一个非常大的数字,在这种情况下,内部函数会阻塞事件循环,我必须确保浏览器能够在计算期间处理事件 我的实现如下所示: function getClosestPrime(num) { return isPrime(num) ? num : getClosestPrime(num-1); } function isPrime(num) { for (let i
function getClosestPrime(num) {
return isPrime(num) ? num : getClosestPrime(num-1);
}
function isPrime(num) {
for (let i = 2; i < num; i++) {
if(num % i === 0) return false;
}
return num !== 1;
}
函数getClosestPrime(num){
返回isPrime(num)?num:getClosesPrime(num-1);
}
函数isPrime(num){
for(设i=2;i提前感谢。在承诺内使用setTimeout如何
function getClosestPrime(num) {
return new Promise(resolve => {
if (isPrime(num)) {
resolve(num);
} else {
setTimeout(() => resolve(getClosestPrime(num-1)), 0);
}
})
}
function isPrime(num) {
for (let i = 2; i < num; i++) {
if(num % i === 0) return false;
}
return num !== 1;
}
setTimeout(() => alert("foo"), 0); // 1st alerted
getClosestPrime(10000000).then(alert); // 3rd
setTimeout(() => alert("bar"), 0); // 2nd
函数getClosestPrime(num){
返回新承诺(解决=>{
if(isPrime(num)){
解析(num);
}否则{
setTimeout(()=>resolve(getClosestPrime(num-1)),0;
}
})
}
函数isPrime(num){
for(设i=2;i因为JavaScript是单线程的,所以最好的解决方案是使用第二个线程来解决问题。这可以通过使用来实现 有了web worker,您的客户端算法就是:
- 创建一个worker
- 当我们希望它计算素数时,给它发送一条消息
- 侦听一条名为“完成”的消息,这表示工作进程已完成
// create the worker
var primeWorker = new Worker('calculate-prime.js');
function doPrimeComputationInWorker(number) {
function handleWorkerCompletion(message) {
if (message.data.command == 'done') {
// update UI using the 'primeNumber' value received in the message
console.log(message.data.primeNumber);
// remove the event listener
primeWorker.removeEventListener('message', handleWorkerCompletion);
}
}
// add the event listener
primeWorker.addEventListener('message', handleWorkerCompletion, false);
// post the number to the worker
primeWorker.postMessage({
'number': number
});
}
代码应该足够简单,以便您遵循,您所要做的就是更改代码,以便在工作人员完成时更新UI
现在您需要web工作者代码。下面是calculate prime.js
的框架:
// add the event listener
self.addEventListener('message', start);
function start(message) {
// get the number value from the message
var number = message.data.number;
// perform the calculation
var nearestPrime = calculateNearestPrime(number);
// return the result
self.postMessage({
'command': 'done',
'primeNumber': nearestPrime
});
}
function calculateNearestPrime(number) {
// your implementation goes here
// return the result
return result;
}
我将把质数的计算留给您,但是这个方法很容易实现,如果您不想自己编写代码,您可以在网上找到JavaScript实现。您可以使用来保存生成的素数列表,并加快未来的计算速度
作为将来的参考,您应该了解和,以便可以使用它们来解决异步问题 对于素数,使用这个。为可能的最大数量生成一次,然后在不计算的情况下使用它。对所有数字进行一次又一次的分析同样,为了实现一个非常简单的优化,在检查除数时,您只需将数字检查到
Math.floor(Math.sqrt(num))
。这将减少一半以上的迭代。您可能需要一个web工作人员在另一个线程中运行它。非常感谢您的回答和详细解释。我还不熟悉workers,所以这是一个练习和了解workers的好机会。Web workers非常适合从UI线程卸载工作。只是不要创建太多(100+),因为每一个都是处理器的新线程。我在handleWorkerCompletion
函数中修复了代码示例worker
应该是primeWorker
。非常感谢,它工作得很好,并且在setTimout的回调没有立即启动时不会阻止事件处理,但有一点延迟(~1000ms)。