브라우저가 기본 약속을 지원하지 않는 경우 마이크로 태스킹을 대기하는 방법은 무엇입니까?


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있습니까?

.then를 사용하여의 마이크로 태스크 를 모방하려고 setTimeout하면 마이크로 태스크가 아닌 매크로 태스크를 큐에 넣게되므로 .then매크로 태스크가 이미 대기중인 경우 잘못 채워진 것이 적시에 실행되지 않습니다.

를 사용하는 솔루션이 MutationObserver있지만 추악한 것처럼 보이며 목적이 아닙니다 MutationObserver. 또한 MutationObserverIE10 및 이전 버전에서는 지원되지 않습니다. 약속을 기본적으로 지원하지 않는 환경에서 마이크로 태스크를 대기시키려는 경우 더 나은 대안이 있습니까?

( 실제로 IE10을 지원하려고 하지는 않습니다. 이것은 약속없이 마이크로 태스킹을 대기하는 방법에 대한 이론적 인 연습 일뿐입니다)


1
성능 중심의 약속 구현, 특히 Bluebird를 살펴 보는 것이 좋습니다. 그것schedule.js역사를 살펴보면 깨달을 것입니다.
베르 기

core-js와 같은 것을 사용하여 Promise를 폴리 파일링 해 보셨습니까?
휴고

답변:


4

우리가 IE에 대해 이야기하고 있다면 setImmediate

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

또한 MutationObserver는 IE10 및 이전 버전에서 지원되지 않습니다.

setImmediateIE10에서 지원됩니다. IE 버전 하나 더하기.
그리고 관심이 있다면 Node.js를 추가하십시오.

MutationObserver를 사용하는 솔루션이 있지만보기 흉하게 보이며 MutationObserver가 아닙니다.

다른 가능한 polyfills 여기 구현의 몇 가지가있다 : https://github.com/YuzuJS/setImmediate/blob/master/setImmediate.js (이 하나가 MDN에서 언급) https://github.com/taylorhakes/ setAsap / blob / master / setAsap.js (더 간단한 것)

그리고 거의 모든 폴리 필로도 추악합니다.

그러나 어쨌든 여기에 본질의 예가 있습니다 (postMessage 사용). 그리고 그것이 가장 추악하다고 생각합니다 (그러나 진정한 polyfill은 아닙니다)

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


위대한 발견, 나는 그들 모두를 좋아한다!

@Snow, 그건 그렇고, 당신은 이론적 인 운동이라고 말했지만, 여전히 궁금합니다 .2019 년 에이 아이디어를 어떻게 보았습니까?
x00

마이크로 태스크가 어떻게 큐잉 될 수 있는지 궁금해했습니다. 더 구체적인 것은 없었습니다. 나는 거기 바라고의 종류이었다 뭔가 약속이 아닌 그들에 대한 액세스를 제공하는 언어에 내장 된,하지만이없는 것 같습니다. 다른 모든 방법 (그러나 바로 그런 종류의 물건을 위해 설계되지 않은 환경 고유의 단점을 호출 참여 볼 일이 어쨌든 일에).

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.