≪ Today I learned. RSS購読
公開日
タグ
JavaScript
著者
ダーシノ(@bc_rikko)

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に出力されます。