ブラウザーがネイティブPromiseをサポートしていない場合、マイクロタスクをキューに入れる方法は?


11

即時のコールバックのタイミングに依存しないコード(マイクロタスクとマクロタスクのような)を書く方が良いですが、とりあえず脇に置いておきましょう。

setTimeoutマクロタスクをキューに入れます。マクロタスクは、少なくとも、すべてのマイクロタスク(およびそれらが生成するマイクロタスク)が完了するまで開始を待機します。次に例を示します。

console.log('Macrotask queued');
setTimeout(function() {
  console.log('Macrotask running');
});
Promise.resolve()
  .then(function() {
    console.log('Microtask running');
  });
console.log('Microtask queued');
console.log('Last line of script');

行動.then解決の約束には、即時の行動は基本的に異なるsetTimeoutコールバック-約束は.thenしても、最初に実行されるsetTimeout最初のキューに入れられました。ただし、Promiseをサポートしているのは最新のブラウザのみです。どのようにすることができ、特別な場合にはマイクロタスクの機能が適切にpolyfilledことPromiseは存在しないのですか?

.thenを使用してのマイクロsetTimeoutタスクを模倣しようとすると、マイクロタスクではなくマクロタスクがキューイングされるため、.thenマクロタスクがすでにキューに登録されている場合、不適切にポリフィルされたものが適切なタイミングで実行されません。

を使用した解決策がありますMutationObserverが、見た目が醜く、それMutationObserverが目的ではありません。また、MutationObserverIE10以前ではサポートされていません。Promiseをネイティブでサポートしていない環境でマイクロタスクをキューに入れたい場合、より良い代替手段はありますか?

(私は実際にはIE10をサポートしようとしているわけではありません。これは、Promiseなしでマイクロタスクをキューに入れる方法についての理論的な演習です)


1
パフォーマンス指向のPromise実装、特にBluebirdを確認することをお勧めします。その歴史をschedule.js見てみると啓発されます。
ベルギ

core-jsなどを使用してPromiseをポリファイリングしてみましたか?
ヒューゴ

回答:


4

IEについて話している場合は、 setImmediate

https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate

また、IE10以前ではMutationObserverはサポートされていません。

setImmediateIE10でサポートされています。つまり、1つのIEバージョンです。
そして、もし興味があれば、さらにNode.jsも。

MutationObserverを使用する解決策がありますが、見た目は醜く、MutationObserverの目的ではありません。

他の可能なポリフィルがあります。ここにいくつかの実装があります:https : //github.com/YuzuJS/setImmediate/blob/master/setImmediate.js(これはMDNで言及されていますhttps://github.com/taylorhakes/ setAsap / blob / master / setAsap.js(より単純なもの)

そして、ほとんどすべてのポリフィルと同様に醜いです。

しかし、とにかく、これはその本質的な例(postMessageを使用)であり、私はそれがすべての中で最も醜くないと思います(ただし、真のポリフィルではありません)。

var setImmediate = (function() {
  var queue = [];

  function on_message(e) {
    if(e.data === "setImmediateMsg") queue.pop()()
  }

  if(window.addEventListener) { // IE9+
    window.addEventListener('message', on_message)
  } else { // IE8
    window.attachEvent('onmessage', on_message)
  }

  return function(fn) {
    queue.unshift(fn)
    window.postMessage("setImmediateMsg", "*")
  }
}())

setTimeout(function() {
  console.log('Macrotask running');
});
console.log('Macrotask queued');
setImmediate(function() {
  console.log('Microtask running');
});
console.log('Microtask queued');
console.log('Last line of script');


素晴らしい発見、私はそれらすべてが好きです!
雪の

@スノー、ところで、理論的な演習だとおっしゃっていましたが、2019年にどうしてこのアイデアに出会ったのでしょうか?
x00

マイクロタスクがどのようにキューに入れられるのか疑問に思っていましたが、これ以上具体的なものはありませんでした。Promises以外に、言語へのアクセスを提供する何かが組み込まれていることを期待していましたが、そうではないようです。他のすべての方法は、(ちょうどそういったことのために設計されていない環境固有の癖を呼び出す関与して見て起こるとにかく仕事に)。

8

私はそれを見たmutationObserver私は、コールバックを保存することにより、IE11でマイクロタスクをキューに入れ、その直後の要素を変更することにより、オブザーバをトリガーするためにアイデアを持っていたので、コールバックがマイクロタスクを使用して、幸運にも、IE11はそれをサポートしています。

var weirdQueueMicrotask = (function() {
  var elementThatChanges = document.createElement('div');
  var callback;
  var bool = false;
  new MutationObserver(function() {
    callback();
  }).observe(elementThatChanges, { childList: true });
  return function(callbackParam) {
    callback = callbackParam;
    elementThatChanges.textContent = bool = !bool;
  };
})();

setTimeout(function() {
  console.log('Macrotask running');
});
console.log('Macrotask queued');
weirdQueueMicrotask(function() {
  console.log('Microtask running');
});
console.log('Microtask queued');
console.log('Last line of script');

IE11を開いて上記の動作を確認できますが、コードが奇妙に見えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.