在下面的最小示例中,旧内容的替换通过 setTimeout
延迟,以便让用户有时间完成查看。与此同时,正在准备新内容,以避免在执行可能代价高昂的任务时阻塞用户界面。
var div = document.getElementById('wrapper');
var newContent = document.createElement('ul');
setTimeout(function() {
var header = div.firstElementChild;
header.innerHTML = 'New Content';
header.nextElementSibling.remove();
div.appendChild(newContent);
}, 2000);
// Make new content while we wait
[1, 10, 100, 1000].forEach(function(x) {
var li = document.createElement('li');
li.innerHTML = 'Factorial of ' + x + ' is ' + factorial(x);
newContent.appendChild(li);
});
function factorial(num) {
if (num === 0) {
return 1;
} else {
return (num * factorial(num - 1));
}
}
<div id='wrapper'>
<h1>Old content</h1>
<p>Read it before it's gone.</p>
</div>
我对这种方法的担忧是,它似乎无法处理 newContent
在替换即将发生时未准备就绪的情况。我也不确定这种方法是否会阻塞用户界面,或者 setTimeout
使用的任务是否会同时执行。
如何确保用户界面在执行可能代价高昂的任务时不会被阻塞并在完成后立即使用它?
最佳答案
长时间运行的计算会阻塞浏览器,这绝不是一个好主意。因此,你应该把它放在网络 worker 中。
如今,使用 promises 等异步工具编写异步代码是更好的做法。这是一种通用的伪代码级方法:
// Create a promise which fulfills after some # of ms.
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Create the worker, kick it off, and
// return a promise which fulfills when the worker reports a result.
function waitWorker() {
const worker = new Worker('factorial.js');
worker.postMessage([1, 10, 100, 1000]);
return new Promise(resolve =>
worker.addEventListener('message', event => resolve(event.data))
);
}
// Wait for both the worker to complete and the two seconds to elapse.
// Then output the data.
Promise.all([timeout(2000), waitWorker()])
.then(values => output(values[1]);
编写 worker 留作练习。
使用异步函数
如果您的环境支持,您还可以使用异步函数更清楚地表达这一点,如下所示:
async function calcAndWait() {
const result = waitWorker(); // Kick off computation.
await timeout(ms); // Wait for two seconds.
output(await result); // Wait for computation to finish and output.
}
关于javascript - 在等待时执行延迟函数所依赖的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39666416/