マイクロタスク・リカバリ・トリック

7417 ワード

Recursion is an operation that a lot of developers are trying to avoid since it is very dangerous, and can break the execution of applications in a fraction of a bug, but it is needed in some scenarios (e.g tree iteration). This post is for technical readers who want to learn how to use recursion efficiently using Microtasks. I assume that you're already familiar with JavaScript event loop mechanism


それで、私の話はあまり長くありません、そして、私が木オブジェクトを横断するためにコードを書く必要があったとき、私の最後の週末に始まりました.
私は再帰的なロジックでコードを作成する必要があったので、スタックが最大スタックフレームに制限されているため、スタックオーバーフロー(RangeError例外)を避けるためにコードを分割する必要がありました.
ブラウザのスタックの制限を確認できますhere
当然、私はタイミングAPI(settimeout/setinterval)を使って反復を「中断」する必要があることを知っていました.
function run() {
    const max = 50000;
    let count = 0;

    const start = performance.now();
    (function run() {
        if (count < max) {
            count++;
            if (count % 100 === 0) {
                setTimeout(run, 0);
            } else {
                run();
            }
        } else {
            console.log(`Done: ${performance.now() - start}`);
        }
    })();
}
私がこの与えられたコードの実行時間をチェックしたとき、私はあまり幸せでなかった(~ 2500 ms)、そして、私はより良い結果を得たかったです.
私は、私の問題に対するより良いアプローチについて考えていました.タイミングAPIの使い方をマイクロタスクに置き換えました.
function run() {
    const max = 50000;
    let count = 0;
    const start = performance.now();

    return new Promise((resolve) => {
        (function _run() {
            if (count < max) {
                count++;
                if (count % 100 === 0) {
                    queueMicrotask(_run);
                } else {
                    _run();
                }
            } else {        
                console.log(`Done: ${performance.now() - start}`);
                resolve(performance.now() - start);
            }
        })();
    });
}
このパターンの実行時間は675.6倍速くなった!(3.7 ms)
Microtask使用方法は、2つの主要な理由でこのようなシナリオをよりよく動作させます.

  • タイミングAPIは決定的ではない
  • ブラウザーは反復的なタイミングAPI呼び出しの上でthrottlingしています
  • タイミングAPI :
  • setTimeout
  • setInterval
  • マイクロタスクの例

  • queueMicrotask
  • Promise
  • マイクロタスク実行対タスク実行
    によるとprocessing model algorithm , the micro-tasks execution アルゴリズムは高速かつ効率的です.スタックが空であるならば、それがするすべてはすべてのマイクロ作業を実行することです(待ち行列管理でない).

  • 結論
    JavaScriptは、重い計算や再帰論理のための言語ではありませんが、できるだけ早く再帰的実行を実行する必要がある場合.
    スタックサイズの制限なしで、マイクロタスクを使用するのに役立ちます.