≪ Today I learned.
RSS購読
    公開日
    更新日
    タグ
    JavaScript
    著者
    ダーシノ

    scheduler.yield()を使い長いタスクに割り込む

    Chrome 129 Betascheduler.yield()が使えるようになった。

    ※Chrome 115でフラグ付きで実装されていた。

    長い処理を実行しているときは、その処理が終わるまで他のイベントを受け付けなくなってしまう。

      +-------------------+   +---------+
    --|     long task     |---| onclick |--->
      +-------------------+   +---------+
    
        このあたりでクリックしてもlong taskが終わるまで反応しない

    scheduler.yield()を使うことで、長い処理の中に割り込むことができる。

      +----+  +----+  +---------+  +----+  +----+
    --| lo |--| ng |--| onclick |--| ta |--| sk |-->
      +----+  +----+  +---------+  +----+  +----+
    
        ここでクリックするとlong taskの途中でも実行できる

    Before: ブロックされる

    サンプルコード

    <button id="click" type="button">Click</button>
    <button id="start" type="button">Start</button>
    function longTask() {
      // 長い処理
      for(let i = 0; i < 10_000_000; i++) {
        const el = document.querySelector('dummytask')
      }
    }
    
    function run() {
      console.group('Blocking')
      let i = 0
      longTask()
      console.log(i++)
    
      longTask()
      console.log(i++)
    
      longTask()
      console.log(i++)
    
      longTask()
      console.log(i++)
    
      longTask()
      console.log(i++)
    
      console.groupEnd('Blocking')
    }
    
    
    const click = document.querySelector('#click')
    click.addEventListener('click', () => console.log('Clicked'))
    
    const start = document.querySelector('#start')
    start.addEventListener('click', () => run())

    実行結果

    > Blocking
    > 0
    > 1
    > 2
    > 3
    > 4
    > Clicked
    > Clicked
    > ...

    After: ブロックされない(scheduler.yield())

    サンプルコード

    ...
    async function run() {
      console.group('Scheduler Yield')
      let i = 0
      longTask()
      console.log(i++)
      await scheduler.yield()
    
      longTask()
      console.log(i++)
      await scheduler.yield()
    
      longTask()
      console.log(i++)
      await scheduler.yield()
    
      longTask()
      console.log(i++)
      await scheduler.yield()
    
      longTask()
      console.log(i++)
      await scheduler.yield()
    
      console.groupEnd('Scheduler Yield')
    }
    ...

    実行結果

    > Scheduler Yield
    > 0
    > Clicked
    > 1
    > Clicked
    > Clicked
    > 2
    > Clicked
    > 3
    > Clicked
    > 4
    > Clicked
    > ...

    デモ

    実行結果はConsoleに出力されます。

    ブラウザ対応状況