1.setIntervalの問題
直接の例:
let startTime = new Date().getTime();
let count = 0;
setInterval(function () {
count++;
console.log(
`与原设定的间隔时差了${
new Date().getTime() - (startTime + count * 1000)
}毫秒`
);
}, 1000);
実行中に少し時間エラーが発生する可能性がありますが、無視してかまいません。
ただし、コードを少し変更してみましょう。
let startTime = new Date().getTime();
let count = 0;
//耗时任务
setInterval(function () {
let i = 0;
while (i++ < 1000000000);
}, 0);
setInterval(function () {
count++;
console.log(
`与原设定的间隔时差了${
new Date().getTime() - (startTime + count * 1000)
}
毫秒`
);
}, 1000);
ミリ秒単位の差が非常に大きくなり、増加し続けることがわかります。このエラーは許容できません。
では、この問題の原因は何ですか?
理由⚠️:の実行メカニズムが原因ですEventLoop
。素人の言葉で言えば、生成された各タスクは直接タスクキューに移動します。各タスクがタスクキューに追加される前に、判断を下す必要があります(最後のタスクがまだキューにあるかどうかを確認します。追加、そうでない場合は追加)。setInterval
setTimeout
push
setInterval
push
setInterval
欠点も明らかです。
- 使用する
setInterval
と、一部の間隔がスキップされます(最後の実行コードが実行されない場合、この実行コードはキューに入れられず、スキップされます) - 複数のタイマーが連続して実行される可能性があります(コードがキューで待機していてまだ実行を開始していない最後の時間、次にタイマーが2番目のコードを追加したとき、最初のコードの待機時間と実行時間は正確に等しい2番目のコード実行)
次に、setTimeoutはSetIntervalを実装します
const myInterval = (fn, time) => {
// 定义一个递归函数持续调用定时器
let executor = (fn, time) => {
timer[key] = setTimeout(() => {
fn();
executor(fn, time);
}, time)
}
executor(fn, time);
}
テスト:テスト結果に問題はありませんが、タイマーをクリアするためmyInterval(()=>{console.log(111)},3000);
に同様の方法をどのように実装しますか?最初に、返される整数が整数の文字列であり、これらの整数が繰り返されない、または連続していないことを調べてみましょう。そうです、これは動作しているときに対応するタイマーを見つけてクリアします。次に、現在定義されているものを保存できますか?clearSetInterval
setTimeOut
setTimeout
clearTimeout
id
mySetInterval
id
var timeWorker = {
}
var mySetInterval= function(fn, time) {
// 定义一个key,来标识此定时器
var key = Symbol();
// 定义一个递归函数,持续调用定时器
var execute = function(fn, time) {
timeWorker[key] = setTimeout(function(){
fn();
execute(fn, time);
}, time)
}
execute(fn, time);
// 返回key
return key;
}
var myClearInterval = function(key) {
if (key in timeWorker) {
clearTimeout(timeWorker[key]);
delete timeWorker[key];
}
}
テストがあります:
let time1 = mySetInterval(() => {
console.log(111)}, 3000);
let time2 = mySetInterval(() => {
console.log(222)}, 3000);
setTimeout(() => {
myClearInterval(time2);
}, 4000)
実現完了✌️!