JSタイマーsetTimeout非同期
7818 ワード
非同期参考文章関数呼び出しと関数の違い まず一つの例を見ます. 間隔は、設定された時間よりも長くなります. タイマーの「アイドリング」問題は、ブラウザがフォーカスを失うと、ユーザがブラウザに関心を持っていないとき、タイマーの出力が遅くなります.例えば、0.5秒を設定して一回実行すると、ブラウザを最小化してから1秒を経過することができます. set Interval set Intevalについては、一つのtimerandだけであり、setTimeoutとは異なる . setTimeoutの関数の参照 どうやってタイマーwindow.clearTimeoutをキャンセルしますか?
次の二つの例を見ると、非同期は結果を待たずに別のコードを実行して、あるコールバック関数に結果を知らせてくれます.
上記の例では、agent関数はコールバック関数である.全体をqueueに伝えて、queueを呼び出してからまた全体に伝えます.コールバック関数といいます.あなたに伝えます.呼び出してください.また送ってください.
非同期とリピートはしばしば同時に現れます.非同期になっても後戻りしないということは、これをやめて結果を返すということになります.
関連するいくつかの問題分析
setTimeoutの中の関数の作用域に出力するiは存在しません.前の段階の作用域に行くとすぐに関数の中からiを探します.直ちに実行関数の中にもiがありません.また、グローバルスコープの中でiを探すと、forサイクルはもう終わりました.iは5です.だから、毎回5を出力します.
setTimeoutの中の関数はiを出力する時、iが見つけられなくて、一級上の作用域に着いたらすぐに関数を実行して探します.3番と違って、今回の直ちに実行関数の中にiがあります.もう大域作用領域にiを探すことはできません.
形参と書くとiが定義されているので、このとき出力されるiは即時実行関数のiであり、このiが入ってきた値は当時の大域のiの値0,1,2,3,4である.
set Timeoutの応用:逆タイマーを作る
//
function fn () { //
return 1;
}
fn(); //
console.log(fn); // ƒ fn() {return 1;}
console.log(fn()); //1
// return
function fn2 () {
return function () {
return 2;
}
}
fn2//
fn2()// function () { return 2; }
fn2()(); //2
タイマーfunction fn (){
console.log(1);
}
setTimeout(fn);
console.log(2);
// 2 1, 2 1
setTimeoutは、出力1のイベントを0秒後に設定します.ブラウザは、現在のコードを全部実行してから、setTimeoutのコードを後で実行します.function fn (){
console.log(1);
}
var timeId = setTimeout(fn);
console.log('id:' + timeId);//1
console.log(2);
timeId = setTimeout(fn);
console.log('id:' + timeId);//2
// setTimeout , setTimeout, setTimeout ,id 。
function fn (){
console.log(1);
console.log(new Date()-0);
}
setTimeout(fn);
console.log(new Date()-0);
// 0, date , 0, , ‘ ’ setTimeout
// ,
setTimeout(fn,500,1,2,3);
function fn () {
console.log(arguments); //[1,2,3]
}
var timerId = setTimeout('console.log(" clearTimeout, ")',3000);
window.clearTimeout(timerId); // setTimeout
var timerId2 = setTimeout('console.log(" clearTimeout, ")',3000);
非同期とコールバック次の二つの例を見ると、非同期は結果を待たずに別のコードを実行して、あるコールバック関数に結果を知らせてくれます.
function queue () {
setTimeout(function () {
return " 233";
},60000); //60s
};
var result = queue();
console.log(result); //undefined queue return, undefined
この場合、匿名関数の戻り値を取得するには、オブジェクトまたは関数を作成して、queueに入力します.queueの匿名関数はreturnをセットしなくてもいいです.設定しても取れないので、returnをセットしないで、直接にこの作成したプロキシ関数を値に取得して出力できます. function queue (agent) { // agent
setTimeout(function () {
agent(" 233"); // return, , agent
},3000); //60s
};
// , , queue ,queue return,
// return, ,
function agent (result) { //
console.log(result);
}
queue(agent); // queue
全体的な考えは、プログラムは次のように実行されます.プロキシ関数を作成して値を得て、setTimeoutの時間間隔が来たら値を取ってプログラムに戻ります.上記の例では、agent関数はコールバック関数である.全体をqueueに伝えて、queueを呼び出してからまた全体に伝えます.コールバック関数といいます.あなたに伝えます.呼び出してください.また送ってください.
非同期とリピートはしばしば同時に現れます.非同期になっても後戻りしないということは、これをやめて結果を返すということになります.
関連するいくつかの問題分析
for (var i = 0; i < 5; i ++) {
console.log(i); //0 1 2 3 4
}
for (var i = 0; i < 5; i ++) {
setTimeout(function () { //for , setTimeout i 5
console.log(i);
},1000*i);
}
第1回目の即時出力5は、第2回目が1000ミリ秒後に出力5回目が2000ミリ秒後に出力5を類推して5回目、jはsetTimeout内部の匿名関数を1秒ごとに印刷してiを出力したい場合、iが見つからない場合は、上のレベル、つまりグローバル中でiを探します.iはすでに5回目です.外部の時間間隔iはグローバルiと同じものです.毎回の値は0,1,2,3,4です.for (var i = 0; i < 5; i ++) {
(function () {
setTimeout(function () {
console.log(i);
},i * 1000);
})(i);
}
第二の問題の結果と同様に、1000乗iのそのiは全体の中のiで、毎回0,1,2,3,4です.setTimeoutの中の関数の作用域に出力するiは存在しません.前の段階の作用域に行くとすぐに関数の中からiを探します.直ちに実行関数の中にもiがありません.また、グローバルスコープの中でiを探すと、forサイクルはもう終わりました.iは5です.だから、毎回5を出力します.
for (var i = 0; i < 5; i ++) {
(function (i) {
setTimeout(function () {
console.log(i);
},i * 1000);
})(i);
}
3番と違って、ここですぐに実行関数が形参を書きました.この形は変数宣言var i=argments[0]に相当します.setTimeoutの中の関数はiを出力する時、iが見つけられなくて、一級上の作用域に着いたらすぐに関数を実行して探します.3番と違って、今回の直ちに実行関数の中にiがあります.もう大域作用領域にiを探すことはできません.
形参と書くとiが定義されているので、このとき出力されるiは即時実行関数のiであり、このiが入ってきた値は当時の大域のiの値0,1,2,3,4である.
for (var i = 0; i < 5; i ++) {
setTimeout((function (i) {
console.log(i);
})(i),i * 1000)
}
第5の問題は依然として作用ドメインチェーンによって理解されています.setTimeoutの中の関数の役割領域で出力されるiは、直ちに関数のiを実行します.これは、形参を定義しています.この形参は毎回受信するiは当時の大域のiの値0,1,2,3,4です.時間間隔のiはグローバルのiです.毎回の値は0,1,2,3,4です.結果を求めてから、第5問に対して、コードを簡単にして、詳しく分析してみます. for (var i = 0; i < 5; i ++) {
var t1 = function (i) {
console.log(i);
};
var t2 = t1(i);
setTimeout(t2,1000*i);
}
コードを分解してから分析します.この時set Timeoutの中で実行されるのはt 2で、t 2はt 1呼び出しの結果、t 1にはreturnが書いていません.デフォルトはundefinedに戻ります.だからt 2はundefinedです. setTimeout(undefined,0);
setTimeout(undefined,1000);
setTimeout(undefined,2000);
setTimeout(undefined,3000);
setTimeout(undefined,4000);
出力の値は、t 1のconsone.log(i)である.私達もはっきりと見ることができます.このiは伝来の当時の毎回のi値0,1,2,3,4です.set Timeoutの応用:逆タイマーを作る
Document
var show = document.querySelector('#show');
var start = document.querySelector('#start');
var pause = document.querySelector('#pause');
var resume = document.querySelector('#resume');
var select = document.querySelector('#mySelect');
// var timeLeft;
// function showtime () {
// show.innerText = timeLeft + ' ';
// timeLeft -= 1;
// if (timeLeft === 0) {
// return;
// }
// setTimeout(showtime,1000);
// }
// start.addEventListener('click',function () {
// var seconds = 60 * parseInt(select.value);
// timeLeft = seconds;
// showtime();
// });
// bug, start , setTimeout
// , start , setTimeout , setTimeout , timerId
var timeLeft;
var lastTimerId; // lastTinmerId
function showtime () {
show.innerText = timeLeft + ' ';
timeLeft -= 1;
if (timeLeft === 0) {
return;
}
lastTimerId = setTimeout(showtime,1000); // seTimeout timerId
}
start.addEventListener('click',function () {
var seconds = 60 * parseInt(select.value);
timeLeft = seconds;
// setTimeout
if (lastTimerId !== undefined) {
window.clearTimeout(lastTimerId);
}
showtime();
pause.disabled = false; // start pause
});
//
// , timeLeft, timeLeft
pause.addEventListener('click',function () {
if (lastTimerId) {
window.clearTimeout(lastTimerId);
}
resume.disabled = false; // pause resume
pause.disabled = true; // pause pause
})
resume.addEventListener('click',function () {
showtime(); // , showTime() timeLeft , timeLeft
pause.disabled = false; // resume pause
resume.disabled = true; // resume , resume
})