激重loopのCPUの負担を抑えたい場合に、よくsetTimeout(fn,0)を連呼するかどうかは定かではないかもしれませんが、それではいささか低速過ぎるという事態に直面しかねません。そういうprogramにおすそ分けする技法を紹介します。
//XMLHttpRequest法
(function(F){
var x=new XMLHttpRequest;
x.onload=function a(){F[0]&&F.shift()()};
this.wait0=function(f){F[F.length]=f;x.send(x.open("GET","data:,"))}
})([])
//script法
(function(F){
function a(e){
F[0]&&F.shift()();
h.removeChild(this);
e.target=null
}
var u="data:,",h=document.getElementsByTagName("head")[0];
this.wait0=function(f){
F[F.length]=f;
f=document.createElement("script");
f.onload=a;f.src=u;h.appendChild(f)
}
})([])
//Blob法
(function(F){
function a(){F[0]&&F.shift()()}
var b=new Blob([]);
this.wait0=function(f){b.text(F[F.length]=f).then(a)}
})([])
//File法
(function(F){
function a(){F[0]&&F.shift()()}
var b=new File([],"");
this.wait0=function(f){b.text(F[F.length]=f).then(a)}
})([])
//FileReader法
(function(F){
function a(){F[0]&&F.shift()()}
var b=new Blob([new Uint8Array(0)]);
this.wait0=function(f){
F[F.length]=f;f=new FileReader;
f.onload=a;f.readAsArrayBuffer(b)}
})([])
//FileReader法2
(function(F){
var b=new Blob([new Uint8Array(0)]),r=new FileReader;
r.onload=a=>{
F[0]&&F.shift()();delete r.result
}
this.wait0=function(f){
F[F.length]=f;r.readAsArrayBuffer(b)
}
})([])
//FileReader法3
(function(F){
function a(){F[0]&&F.shift()()}
var b=new Blob([""]);
this.wait0=function(f){
F[F.length]=f;f=new FileReader;
f.onloadstart=a;f.readAsArrayBuffer(b)}
})([])
//Image法
(function(F){
function a(){F[0]&&F.shift()()}
var s="data:image/gif;base64,R0lGODdhAQABAAAAAAA";
this.wait0=function(f){
F[F.length]=f;f=new Image;
f.onload=a;f.src=s
}
})([])
//Image法2
(function(F){
var i=new Image,s="data:image/gif;base64,R0lGODdhAQABAAAAAAA";
i.onload=function(){
F[0]&&F.shift()();delete i.src
};
this.wait0=function(f){F[F.length]=f;i.src=s}
})([])
//postMessage法
(function(a){
var F=[],hit="\0";
a.wait0=function(f){
F[F.length]=f;a.postMessage(hit,"*")
};
a.onmessage=function(e){
if(e.source===a&&e.data===hit)
e.stopPropagation(),F[0]&&F.shift()()
}
})(this);
//MessageChannel法
(f=>{var c=new MessageChannel,p={},o=p;
c.port1.onmessage=f=>{p=p.p;p.f();delete p.f};
f.wait0=f=>{o=o.p={f:f};c.port2.postMessage(0)}
})(this);
いずれもwait0(function(){...}) のように使います(setTimeout(function(){...},0) のようなもの)。 速度を比較すると以下のような感じになるかも
MessageChannel >> postMessage > Image >>> File, FileReader > script > XMLHttpRequest
var start=+new Date,times=[];
wait0(function run(){
times.push(Date.now()-start); // 前の呼び出しからの遅延を覚える
if(start+100<Date.now())document.write(times.length," ",times.join(" ")); // 100ms 後に遅延を表示
else wait0(run,0)// もしくは再schedule
},0)