Đin*_*Huy 6 javascript asynchronous
我了解如何使用setTimeout
函数,但我找不到创建类似函数的方法。
我有一个例子:
setTimeout(() => {
console.log('3s');
}, 3000);
while(1);
Run Code Online (Sandbox Code Playgroud)
结果是setTimeout
回调永远不会调用,所以我认为它像每个 js 其他函数一样使用相同的线程。但是当它检查时间是否到达时?以及它如何做到这一点?
为了避免误解,我更新了我的问题。
我找不到在指定时间后创建带有回调的异步函数的方法(不使用setTimeout
也不阻塞整个线程)。这个功能setTimeout
对我来说就像一个奇迹。我想了解它是如何工作的。
只是为了游戏,因为我真的不明白为什么你不能使用 setTimeout ......
要创建非阻塞计时器,而不使用 setTimeout/setInterval 方法,您只有两种方法:
一种简单的实现是使用MessageEvent接口并轮询直到时间已到。但这对于长时间的超时来说并不是真正的建议......
function myTimer(cb, ms) {
var now = performance.now();
window.addEventListener('message', handleMessage);
postMessage('myTimer', '*');
function handleMessage(evt) {
if(evt.data === 'myTimer') {
if(performance.now() - now >= ms) {
window.removeEventListener('message', handleMessage);
cb();
}
else {
postMessage('myTimer', '*');
}
}
}
}
myTimer(()=>console.log('world'), 2000);
myTimer(()=>console.log('hello'), 200);
Run Code Online (Sandbox Code Playgroud)
因此,如果可用,人们可能希望使用Web Audio API和AudioScheduledSourceNode,它们充分利用了高精度音频上下文自己的时钟:
function myTimer(cb, ms) {
if(!myTimer.ctx) myTimer.ctx = new (window.AudioContext || window.webkitAudioContext)();
var ctx = myTimer.ctx;
var silence = ctx.createGain();
silence.gain.value = 0;
var note = ctx.createOscillator();
note.connect(silence);
silence.connect(ctx.destination);
note.onended = function() { cb() };
note.start(0);
note.stop(ctx.currentTime + (ms / 1000));
}
myTimer(()=>console.log('world'), 2000);
myTimer(()=>console.log('hello'), 200);
Run Code Online (Sandbox Code Playgroud)
是的,使用Web Workers我们可以运行无限循环而不会杀死我们的网页:
function myTimer(cb, ms) {
var workerBlob = new Blob([mytimerworkerscript.textContent], {type: 'application/javascript'});
var url = URL.createObjectURL(workerBlob);
var worker = new Worker(url);
worker.onmessage = function() {
URL.revokeObjectURL(url);
worker.terminate();
cb();
};
worker.postMessage(ms);
}
myTimer(()=>console.log('world'), 2000);
myTimer(()=>console.log('hello'), 200);
Run Code Online (Sandbox Code Playgroud)
<script id="mytimerworkerscript" type="application/worker-script">
self.onmessage = function(evt) {
var ms = evt.data;
var now = performance.now();
while(performance.now() - now < ms) {}
self.postMessage('done');
}
</script>
Run Code Online (Sandbox Code Playgroud)