Tarayıcı yerel Sözleri desteklemiyorsa bir mikro görev nasıl sıralanır?


11

Anında geri aramaların zamanlamasına dayanmayan kod yazmak daha iyidir (mikro görevler ve makro görevler gibi), ama bunu bir kenara bırakalım.

setTimeouten azından tüm mikro görevler (ve ürettikleri mikro görevler) bitene kadar başlamayı bekleyen bir makro görevi sıralar. İşte bir örnek:

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Çözülmüş bir Sözün üzerindeki davranışı temel olarak bir setTimeoutgeri çağrının davranışından temel olarak farklıdır - .thenİlk önce setTimeoutsıraya alınmış olsa bile Söz önce çalışır. Ancak Promises sadece modern tarayıcıları desteklemektedir. Bir mikro görevin özel işlevselliği yoksa düzgün şekilde nasıl doldurulabilir Promise?

.thenKullanarak bir mikro görevini taklit etmeye çalışırsanız setTimeout, bir mikro görev yerine bir makro görev sıraya koyacaksınız, bu nedenle .thenbir makro görev zaten kuyruğa alınmışsa, kötü doldurulmuş içerik doğru zamanda çalışmaz.

Kullanan bir çözüm var MutationObserver, ama çirkin görünüyor ve MutationObserverbunun için bir şey yok . Ayrıca, MutationObserverIE10 ve önceki sürümlerde desteklenmez. Vaatleri doğal olarak Promises'ı desteklemeyen bir ortamda bir mikro görev sıralamak istiyorsa, daha iyi alternatifler var mı?

( Aslında IE10'u desteklemeye çalışmıyorum - bu sadece mikro görevlerin Vaatler olmadan nasıl sıraya alınabileceğine dair teorik bir egzersizdir)


1
Performansa yönelik, özellikle de Bluebird gibi vaat uygulamalarına göz atmanızı öneririm. Tarihineschedule.js bir göz atmak aydınlatıcı olacaktır.
Bergi

Core-js gibi bir şey kullanarak Sözü çoklu dosyalamayı denediniz mi?
Hugo

Yanıtlar:


4

IE hakkında konuşuyorsak, setImmediate

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

Ayrıca, MutationObserver IE10 ve önceki sürümlerde desteklenmez.

setImmediateIE10'da desteklenir. Yani artı bir IE sürümü.
Ve eğer ilgileniyorsanız, artı Node.js.

MutationObserver'ı kullanan bir çözüm var, ama çirkin görünüyor ve MutationObserver'ın amacı bu değil.

Başka olası çoklu dolgular da var, işte birkaç uygulama: https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js (bu MDN'de belirtilmiştir) https://github.com/taylorhakes/ setAsap / blob / master / setAsap.js (daha basit bir tane)

Ve neredeyse tüm çoklu dolgular gibi onlar da çirkin.

Ama neyse, işte özünde bir örnek (postMessage kullanarak) ve bence en çirkin olanı (ama aynı zamanda gerçek bir çoklu dolgu)

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');


Harika bulgular, hepsini seviyorum!
Kar

@Bu, bu arada, bunun teorik bir egzersiz olduğunu söyledin, ama hala merak ediyorum, 2019'da bu fikirle nasıl karşılaştın?
x00

Sadece mikro görevlerin nasıl sıraya alınabileceğini merak ediyordum, gerçekten daha spesifik bir şey yoktu. Sözler dışında, onlara erişim sağlayan dilde yerleşik bir şey olmasını umuyordum , ama öyle görünmüyor. Diğer tüm yöntemleri (ama sadece bu tür bir şey için tasarlanmış değildi ortama özgü tuhaflıklar yürütmesini dahil etmek bakmak gerçekleşmesi zaten işe).
Kar,

8

mutationObserverGeri aramaların mikro görevler kullandığını gördüm ve neyse ki IE11 bunu destekliyor, bu yüzden geri çağrıyı kaydederek ve hemen bir öğeyi değiştirerek gözlemciyi tetikleyerek IE11'de bir mikro görev sıraya koyma fikrim vardı:

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'i açabilir ve yukarıdaki çalışmayı görebilirsiniz, ancak kod garip görünüyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.