setTimeoutはsetIntervalを実装します

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欠点も明らかです

  1. 使用するsetIntervalと、一部の間隔がスキップされます(最後の実行コードが実行されない場合、この実行コードはキューに入れられず、スキップされます)
  2. 複数のタイマーが連続して実行される可能性があります(コードがキューで待機していてまだ実行を開始していない最後の時間、次にタイマーが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 idmySetInterval 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)

ここに画像の説明を挿入
実現完了✌️!

おすすめ

転載: blog.csdn.net/weixin_44761091/article/details/123983972