Joe*_*oey 6 javascript node.js electron
window.requestAnimationFrame()对于不阻止I/O的无限循环,是否有更快的替代方案?
我在循环中所做的与动画无关,所以我不关心下一帧何时准备就绪,并且我已经阅读window.requestAnimationFrame()了显示器的刷新率或至少等待直到可以绘制帧.
我也尝试了以下内容:
function myLoop() {
// stuff in loop
setTimeout(myLoop, 4);
}
Run Code Online (Sandbox Code Playgroud)
(4是因为这是最小间隔setTimeout,较小的值仍然默认为4.)但是,我需要比这更好的分辨率.
那里有更好的表现吗?
我基本上需要一个非阻塞版本while(true).
有两件事会比这更早出现setTimeout:
process.nextTick 回调(NodeJS特定):
该
process.nextTick()方法将回调添加到"下一个滴答队列".一旦事件循环的当前转弯转到完成,将调用当前在下一个滴答队列中的所有回调.这不是一个简单的别名
setTimeout(fn, 0).效率更高.它在事件循环的后续滴答中触发任何其他I/O事件(包括定时器)之前运行.
承诺结算通知
因此,这些可能是您的工具带的工具,可以混合使用其中一个或两个,setTimeout以实现您想要的平衡.
细节:
您可能知道,给定的JavaScript线程基于任务队列运行(规范将其称为作业队列); 你可能知道,浏览器中有一个主要的默认UI线程,NodeJS运行一个线程.
但事实上,在现代实现中至少有两个任务队列:我们都想到的主要任务队列(在哪里setTimeout和事件处理程序放置他们的任务),以及在处理主体期间放置某些异步操作的"微任务"队列任务(或"macrotask").一旦macrotask完成,在主队列中的下一个macrotask之前处理那些微任务 - 即使下一个macrotask在微任务之前排队.
nextTick回调和承诺结算通知都是微任务.因此,调度要么调度异步回调,要么调度将在下一个主要任务之前发生.
我们可以在浏览器中看到setInterval和一个承诺解析链:
let counter = 0;
// setInterval schedules macrotasks
let timer = setInterval(() => {
$("#ticker").text(++counter);
}, 100);
// Interrupt it
$("#hog").on("click", function() {
let x = 300000;
// Queue a single microtask at the start
Promise.resolve().then(() => console.log(Date.now(), "Begin"));
// `next` schedules a 300k microtasks (promise settlement
// notifications), which jump ahead of the next task in the main
// task queue; then we add one at the end to say we're done
next().then(() => console.log(Date.now(), "End"));
function next() {
if (--x > 0) {
if (x === 150000) {
// In the middle; queue one in the middle
Promise.resolve().then(function() {
console.log(Date.now(), "Middle");
});
}
return Promise.resolve().then(next);
} else {
return 0;
}
}
});
$("#stop").on("click", function() {
clearInterval(timer);
});Run Code Online (Sandbox Code Playgroud)
<div id="ticker"> </div>
<div><input id="stop" type="button" value="Stop"></div>
<div><input id="hog" type="button" value="Hog"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>Run Code Online (Sandbox Code Playgroud)
当你运行它并单击Hog按钮时,请注意计数器显示屏是如何冻结的,然后再继续运行.这是因为在它之前安排了300,000个微型计划.另请注意我们编写的三条日志消息的时间戳(它们不会出现在代码段控制台中,直到macrotask显示它们,但时间戳显示我们何时记录它们).
所以基本上,你可以安排一堆微任务,并定期让那些用完并运行下一个macrotask.
注意:我已经setInterval在代码段中使用了浏览器示例,但是setInterval,具体来说,对于使用NodeJS的类似实验可能不是一个好的选择,因为NodeJS setInterval与浏览器中的有点不同,并且具有一些令人惊讶的时序特征.
| 归档时间: |
|
| 查看次数: |
827 次 |
| 最近记录: |