ä¸ä¸ªå¾®ä»»å¡ï¼microtaskï¼å°±æ¯ä¸ä¸ªç®çç彿°ï¼å½å建该微任å¡ç彿°æ§è¡ä¹åï¼å¹¶ä¸åªæå½ Javascript è°ç¨æ 为空ï¼èæ§å¶æå°æªè¿è¿ç»è¢«ç¨æ·ä»£çç¨æ¥é©±å¨èæ¬æ§è¡ç¯å¢çäºä»¶å¾ªç¯ä¹åï¼è¯¥å¾®ä»»å¡æä¼è¢«æ§è¡ãäºä»¶å¾ªç¯æ¢å¯è½æ¯æµè§å¨ç主äºä»¶å¾ªç¯ä¹å¯è½æ¯è¢«ä¸ä¸ª web worker æé©±å¨çäºä»¶å¾ªç¯ãè¿ä½¿å¾ç»å®ç彿°å¨æ²¡æå ¶ä»èæ¬æ§è¡å¹²æ°çæ åµä¸è¿è¡ï¼ä¹ä¿è¯äºå¾®ä»»å¡è½å¨ç¨æ·ä»£çææºä¼å¯¹è¯¥å¾®ä»»å¡å¸¦æ¥çè¡ä¸ºååºååºä¹åè¿è¡ã
JavaScript ä¸ç promise å Mutation Observer API é½ä½¿ç¨å¾®ä»»å¡éåå»è¿è¡å®ä»¬çåè°å½æ°ï¼ä½å½è½å¤æ¨è¿å·¥ä½ç´å°å½åäºä»¶å¾ªç¯è¿ç¨å®ç»æ¶ï¼ä¹æ¯å¯ä»¥æ§è¡å¾®ä»»å¡çæ¶æºã为äºå
è®¸ç¬¬ä¸æ¹åºãæ¡æ¶ãpolyfill è½ä½¿ç¨å¾®ä»»å¡ï¼å¨ Window
å WorkerGlobalScope
æ¥å£ä¸æ´é²äº queueMicrotask()
æ¹æ³ã
ä¸ºäºæ£ç¡®å°è®¨è®ºå¾®ä»»å¡ï¼é¦å æå¥½ç¥éä»ä¹æ¯ä¸ä¸ª JavaScript ä»»å¡ä»¥å微任å¡å¦ä½åºå«äºä»»å¡ãè¿éæ¯ä¸ä¸ªå¿«éãç®åçè§£éï¼ä½è¥ä½ æ³äºè§£æ´å¤ç»èï¼å¯ä»¥é 读è¿ç¯æç« ä¸çä¿¡æ¯ In depth: Microtasks and the JavaScript runtime environment.
ä»»å¡ä¸ä¸ªä»»å¡ï¼taskï¼å°±æ¯ç±æ§è¡è¯¸å¦ä»å¤´æ§è¡ä¸æ®µç¨åºãæ§è¡ä¸ä¸ªäºä»¶åè°æä¸ä¸ª interval/timeout 被触åä¹ç±»çæ åæºå¶è被è°åº¦çä»»æ JavaScript 代ç ãè¿äºé½å¨ä»»å¡éåï¼task queueï¼ä¸è¢«è°åº¦ã
å¨ä»¥ä¸æ¶æºï¼ä»»å¡ä¼è¢«æ·»å å°ä»»å¡éåï¼
<script>
å
ç´ ä¸è¿è¡ä»£ç ï¼ãsetTimeout()
æ setInterval()
å建ç timeout æ intervalï¼ä»¥è´ç¸åºçåè°å½æ°è¢«æ·»å å°ä»»å¡éåæ¶ãäºä»¶å¾ªç¯é©±å¨ä½ çä»£ç æç §è¿äºä»»å¡æéç顺åºï¼ä¸ä¸ªæ¥ä¸ä¸ªå°å¤çå®ä»¬ãå¨äºä»¶å¾ªç¯ç忬¡è¿ä»£ä¸ï¼å°æ§è¡ä»»å¡éå䏿æ§çå¯è¿è¡ä»»å¡ãä¹åï¼å¾®ä»»å¡å°è¢«æ§è¡ï¼ç´å°å¾®ä»»å¡éå为空ï¼ç¶åæµè§å¨å¯ä»¥éæ©æ´æ°æ¸²æãç¶åæµè§å¨ç»§ç»è¿è¡äºä»¶å¾ªç¯çä¸ä¸æ¬¡è¿ä»£ã
微任å¡èµ·å微任å¡ï¼microtaskï¼åä»»å¡ä¹é´çå·®å¼çèµ·æ¥ä¸å¤§ãå®ä»¬å¾ç¸ä¼¼ï¼é½ç±ä½äºæä¸ªéåç JavaScript 代ç ç»æå¹¶å¨åéçæ¶åè¿è¡ã使¯ï¼åªæå¨è¿ä»£å¼å§æ¶éåä¸åå¨ç任塿ä¼è¢«äºä»¶å¾ªç¯ä¸ä¸ªæ¥ä¸ä¸ªå°è¿è¡ï¼è¿åå¤ç微任å¡é忝æ®ä¸ºä¸åçã
æä¸¤ç¹å ³é®çåºå«ã
é¦å ï¼æ¯å½ä¸ä¸ªä»»å¡åå¨ï¼äºä»¶å¾ªç¯é½ä¼æ£æ¥è¯¥ä»»å¡æ¯å¦æ£ææ§å¶æäº¤ç»å ¶ä» JavaScript 代ç ãå¦è¥ä¸ç¶ï¼äºä»¶å¾ªç¯å°±ä¼è¿è¡å¾®ä»»å¡éåä¸çææå¾®ä»»å¡ãæ¥ä¸æ¥å¾®ä»»å¡å¾ªç¯ä¼å¨äºä»¶å¾ªç¯çæ¯æ¬¡è¿ä»£ä¸è¢«å¤ç夿¬¡ï¼å æ¬å¤çå®äºä»¶åå ¶ä»åè°ä¹åã
å
¶æ¬¡ï¼å¦æä¸ä¸ªå¾®ä»»å¡éè¿è°ç¨ queueMicrotask()
ï¼åéåä¸å å
¥äºæ´å¤ç微任å¡ï¼åé£äºæ°å å
¥ç微任å¡ä¼æ©äºä¸ä¸ä¸ªä»»å¡è¿è¡ãè¿æ¯å 为äºä»¶å¾ªç¯ä¼æç»è°ç¨å¾®ä»»å¡ç´è³éå䏿²¡æçåçï¼å³ä½¿æ¯å¨ææ´å¤å¾®ä»»å¡æç»è¢«å å
¥çæ
åµä¸ã
è¦åï¼ å 为微任å¡èªèº«å¯ä»¥å ¥åæ´å¤ç微任å¡ï¼ä¸äºä»¶å¾ªç¯ä¼æç»å¤ç微任å¡ç´è³éå为空ï¼é£ä¹å°±åå¨ä¸ç§ä½¿å¾äºä»¶å¾ªç¯æ å°½å¤ç微任å¡ççå®é£é©ãå¦ä½å¤çéå½å¢å 微任塿¯è¦è°¨æ èè¡çã
使ç¨å¾®ä»»å¡å¨è°è®ºæ´å¤ä¹åï¼å次注æå°ä¸ç¹æ¯éè¦çï¼é£å°±æ¯å¦æå¯è½çè¯ï¼å¤§é¨åå¼åè å¹¶ä¸åºè¯¥è¿å¤ç使ç¨å¾®ä»»å¡ãå¨åºäºç°ä»£æµè§å¨ç JavaScript å¼å䏿ä¸ä¸ªé«åº¦ä¸ä¸åçç¹æ§ï¼é£å°±æ¯å è®¸ä½ è°åº¦ä»£ç 跳转å°å ¶ä»äºæ ä¹åï¼èé£äºäºæ 忬æ¯å¤äºç¨æ·è®¡ç®æºä¸ä¸å¤§å çå¾ åççäºæ éåä¹ä¸çãæ»¥ç¨è¿ç§è½åå°å¸¦æ¥æ§è½é®é¢ã
å ¥å微任å¡å°±å
¶æ¬èº«èè¨ï¼åºè¯¥ä½¿ç¨å¾®ä»»å¡çå
¸åæ
åµï¼è¦ä¹åªæå¨æ²¡æå
¶ä»åæ³çæ¶åï¼è¦ä¹æ¯å½åå»ºæ¡æ¶æåºæ¶éè¦ä½¿ç¨å¾®ä»»å¡è¾¾æå
¶åè½ãè½ç¶å¨è¿å»è¦ä½¿å¾å
¥åå¾®ä»»å¡æä¸ºå¯è½æå¯ç¨çæå·§ï¼æ¯å¦å建ä¸ä¸ªç«å³å
ç°ç promiseï¼ï¼ä½æ°å å
¥ç queueMicrotask()
æ¹æ³å¢å äºä¸ç§æ åçæ¹å¼ï¼å¯ä»¥å®å
¨çå¼å
¥å¾®ä»»å¡èé¿å
使ç¨é¢å¤çæå·§ã
éè¿å¼å
¥ queueMicrotask()
ï¼ç±æ¦æ¶©å°ä½¿ç¨ promise å»å建微任å¡è带æ¥çé£é©å°±å¯ä»¥è¢«é¿å
äºã䏾便¥è¯´ï¼å½ä½¿ç¨ promise åå»ºå¾®ä»»å¡æ¶ï¼ç±åè°æåºçå¼å¸¸è¢«æ¥å为 rejected promises è䏿¯æ åå¼å¸¸ãåæ¶ï¼å建å鿝 promise 带æ¥äºäºä»¶åå
åæ¹é¢çé¢å¤å¼éï¼è¿æ¯æ£ç¡®å
¥å微任å¡ç彿°åºè¯¥é¿å
çã
ç®åçä¼ å
¥ä¸ä¸ª JavaScript Function
ï¼ä»¥å¨ queueMicrotask()
æ¹æ³ä¸å¤ç微任塿¶ä¾å
¶ä¸ä¸æè°ç¨å³å¯ï¼åå³äºå½åæ§è¡ä¸ä¸æï¼queueMicrotask()
以å®ä¹çå½¢å¼è¢«æ´é²å¨ Window
æ Worker
æ¥å£ä¸ã
queueMicrotask(() => {
/* 微任å¡ä¸å°è¿è¡ç代ç */
});
微任å¡å½æ°æ¬èº«æ²¡æåæ°ï¼ä¹ä¸è¿åå¼ã
使¶ä½¿ç¨å¾®ä»»å¡å¨æ¬ç« èä¸ï¼æä»¬æ¥çç微任å¡ç¹å«æç¨çåºæ¯ãé常ï¼è¿äºåºæ¯å ³ä¹ææææ£æ¥ç»æãæ§è¡æ¸ ççï¼å ¶æ¶æºæäºä¸æ®µ JavaScript æ§è¡ä¸ä¸æä¸»ä½çéåºï¼ä½æ©äºä»»ä½äºä»¶å¤ç彿°ãtimeouts æ intervals åå ¶ä»åè°è¢«æ§è¡ã
使¶æ¯é£ç§æç¨çæ¶åï¼
使ç¨å¾®ä»»å¡çæä¸»è¦åå ç®åå½çº³ä¸ºï¼ç¡®ä¿ä»»å¡é¡ºåºçä¸è´æ§ï¼å³ä¾¿å½ç»æææ°æ®æ¯åæ¥å¯ç¨çï¼ä¹è¦åæ¶åå°æä½ä¸ç¨æ·å¯æç¥å°çå»¶è¿è带æ¥çé£é©ã
ä¿è¯æ¡ä»¶æ§ä½¿ç¨ promises æ¶ç顺åºå¾®ä»»å¡å¯è¢«ç¨æ¥ç¡®ä¿æ§è¡é¡ºåºæ»æ¯ä¸è´çä¸ç§æ
å½¢ï¼æ¯å½ promise 被ç¨å¨ä¸ä¸ª if...else
è¯å¥ï¼æå
¶ä»æ¡ä»¶æ§è¯å¥ï¼ä¸ãä½å¹¶ä¸å¨å
¶ä»åå¥ä¸çæ¶åãèèå¦ä¸ä»£ç ï¼
customElement.prototype.getData = url => {
if (this.cache[url]) {
this.data = this.cache[url];
this.dispatchEvent(new Event("load"));
} else {
fetch(url).then(result => result.arrayBuffer()).then(data => {
this.cache[url] = data;
this.data = data;
this.dispatchEvent(new Event("load"));
)};
}
};
è¿æ®µä»£ç 带æ¥çé®é¢æ¯ï¼éè¿å¨ if...else
è¯å¥çå
¶ä¸ä¸ä¸ªåæ¯ï¼æ¤ä¾ä¸ä¸ºç¼åä¸çå¾çå°åå¯ç¨æ¶ï¼ä¸ä½¿ç¨ä¸ä¸ªä»»å¡è promise å
å«å¨ else
åå¥ä¸ï¼æä»¬é¢ä¸´äºæä½é¡ºåºå¯è½ä¸åçå±å¿ï¼æ¯æ¹è¯´ï¼åä¸é¢çèµ·æ¥çè¿æ ·ï¼
element.addEventListener("load", () => console.log("Loaded data"));
console.log("Fetching data...");
element.getData();
console.log("Data fetched");
è¿ç»æ§è¡ä¸¤æ¬¡è¿æ®µä»£ç ä¼å½¢æä¸è¡¨ä¸çç»æï¼
æ°æ®æªç¼åçç»æï¼å·¦ï¼vs. ç¼åä¸ææ°æ®çç»æ æ°æ®æªç¼å æ°æ®å·²ç¼åFetching data Data fetched Loaded data
Fetching data Loaded data Data fetched
çè³æ´ç³çæ¯ï¼ææ¶å
ç´ ç data
屿§ä¼è¢«è®¾ç½®ï¼è¿ææ¶å½è¿æ®µä»£ç ç»æè¿è¡æ¶å´ä¸ä¼è¢«è®¾ç½®ã
æä»¬å¯ä»¥éè¿å¨ if
åå¥é使ç¨ä¸ä¸ªå¾®ä»»å¡æ¥ç¡®ä¿æä½é¡ºåºçä¸è´æ§ï¼ä»¥è¾¾å°å¹³è¡¡ä¸¤ä¸ªåå¥çç®çï¼
customElement.prototype.getData = url => {
if (this.cache[url]) {
queueMicrotask(() => {
this.data = this.cache[url];
this.dispatchEvent(new Event("load"));
});
} else {
fetch(url).then(result => result.arrayBuffer()).then(data => {
this.cache[url] = data;
this.data = data;
this.dispatchEvent(new Event("load"));
)};
}
};
éè¿å¨ä¸¤ç§æ
åµä¸åèªé½éè¿ä¸ä¸ªå¾®ä»»å¡ï¼if
ä¸ç¨çæ¯ queueMicrotask()
è else
åå¥ä¸éè¿ fetch()
使ç¨äº promiseï¼å¤çäºè®¾ç½® data
å触å load
äºä»¶ï¼å¹³è¡¡äºä¸¤ä¸ªåå¥ã
ä¹å¯ä»¥ä½¿ç¨å¾®ä»»å¡ä»ä¸åæ¥æºå°å¤ä¸ªè¯·æ±æ¶éå°åä¸çæ¹å¤çä¸ï¼ä»èé¿å 对å¤çå类工ä½ç夿¬¡è°ç¨å¯è½é æçå¼éã
ä¸é¢ç代ç çæ®µå建äºä¸ä¸ªå½æ°ï¼å°å¤ä¸ªæ¶æ¯æ¾å ¥ä¸ä¸ªæ°ç»ä¸æ¹å¤çï¼éè¿ä¸ä¸ªå¾®ä»»å¡å¨ä¸ä¸æéåºæ¶å°è¿äºæ¶æ¯ä½ä¸ºåä¸ç对象åéåºå»ã
const messageQueue = [];
let sendMessage = (message) => {
messageQueue.push(message);
if (messageQueue.length === 1) {
queueMicrotask(() => {
const json = JSON.stringify(messageQueue);
messageQueue.length = 0;
fetch("url-of-receiver", json);
});
}
};
å½ sendMessage()
被è°ç¨æ¶ï¼æå®çæ¶æ¯é¦å
被æ¨å
¥æ¶æ¯éåæ°ç»ãæ¥çäºæ
å°±åå¾æè¶£äºã
妿æä»¬åå å
¥æ°ç»çæ¶æ¯æ¯ç¬¬ä¸æ¡ï¼å°±å
¥åä¸ä¸ªå°ä¼åéä¸ä¸ªæ¹å¤çç微任å¡ãç
§æ§ï¼å½ JavaScript æ§è¡è·¯å¾å°è¾¾é¡¶å±ï¼æ°å¨è¿è¡åè°ä¹åï¼é£ä¸ªå¾®ä»»å¡å°ä¼æ§è¡ãè¿æå³çä¹åçé´ææå
é æç对 sendMessage()
çä»»ä½è°ç¨é½ä¼å°å
¶åèªçæ¶æ¯æ¨å
¥æ¶æ¯éåï¼ä½å¿äºå
¥å微任å¡é»è¾ä¹åçæ°ç»é¿åº¦æ£æ¥ï¼ä¸ä¼ææ°ç微任å¡å
¥åã
å½å¾®ä»»å¡è¿è¡ä¹æ¶ï¼çå¾
å®å¤ççå¯è½æ¯ä¸ä¸ªæè¥å¹²æ¡æ¶æ¯çæ°ç»ã微任å¡å½æ°å
æ¯éè¿ JSON.stringify()
æ¹æ³å°æ¶æ¯æ°ç»ç¼ç 为 JSONãå
¶åï¼æ°ç»ä¸çå
容就ä¸åéè¦äºï¼æä»¥æ¸
空 messageQueue
æ°ç»ãæåï¼ä½¿ç¨ fetch()
æ¹æ³å°ç¼ç åç JSON å徿å¡å¨ã
è¿ä½¿å¾å䏿¬¡äºä»¶å¾ªç¯è¿ä»£æé´åççæ¯æ¬¡ sendMessage()
è°ç¨å°å
¶æ¶æ¯æ·»å å°åä¸ä¸ª fetch()
æä½ä¸ï¼èä¸ä¼è®©è¯¸å¦ timeouts çå
¶ä»å¯è½ç宿¶ä»»å¡æ¨è¿ä¼ éã
æå¡å¨å°æ¥å° JSON å符串ï¼ç¶å大æ¦ä¼å°å ¶è§£ç å¹¶å¤çå ¶ä»ç»ææ°ç»ä¸æ¾å°çæ¶æ¯ã
ä¾å ç®å微任å¡ç¤ºä¾å¨è¿ä¸ªç®åçä¾åä¸ï¼æä»¬å°çå°å ¥åä¸ä¸ªå¾®ä»»å¡åï¼ä¼å¼èµ·å ¶åè°å½æ°å¨é¡¶å±èæ¬å®æ¯åè¿è¡ã
JavaScriptlet logElem = document.getElementById("log");
let log = (s) => (logElem.innerHTML += s + "<br>");
å¨ä¸é¢ç代ç ä¸ï¼æä»¬çå°å¯¹ queueMicrotask()
ç䏿¬¡è°ç¨è¢«ç¨æ¥è°åº¦ä¸ä¸ªå¾®ä»»å¡ä»¥ä½¿å
¶è¿è¡ãè¿æ¬¡è°ç¨å
å«äº log()
ï¼ä¸ä¸ªç®åçåå±å¹è¾åºæåçèªå®ä¹å½æ°ã
log("Before enqueueing the microtask");
queueMicrotask(() => {
log("The microtask has run.");
});
log("After enqueueing the microtask");
ç»æ timeout å微任å¡ç示ä¾
å¨è¿ä¸ªä¾åä¸ï¼ä¸ä¸ª timeout å¨ 0 毫ç§å被触åï¼æè
"å°½å¯è½å¿«"ï¼ãè¿æ¼ç¤ºäºå½è°ç¨ä¸ä¸ªæ°ä»»å¡ï¼å¦éè¿ä½¿ç¨ setTimeout()
ï¼æ¶çâå°½å¯è½å¿«âæå³çä»ä¹ï¼ä»¥åæ¯ä¹äºä½¿ç¨ä¸ä¸ªå¾®ä»»å¡çä¸åã
let logElem = document.getElementById("log");
let log = (s) => (logElem.innerHTML += s + "<br>");
å¨ä¸é¢ç代ç ä¸ï¼æä»¬çå°å¯¹ queueMicrotask()
ç䏿¬¡è°ç¨è¢«ç¨æ¥è°åº¦ä¸ä¸ªå¾®ä»»å¡ä»¥ä½¿å
¶è¿è¡ãè¿æ¬¡è°ç¨å
å«äº log()
ï¼ä¸ä¸ªç®åçåå±å¹è¾åºæåçèªå®ä¹å½æ°ã
以ä¸ä»£ç è°åº¦äºä¸ä¸ª 0 毫ç§å触åç timeoutï¼èåå
¥åäºä¸ä¸ªå¾®ä»»å¡ãåå被对 log()
çè°ç¨å
ä½ï¼è¾åºéå çä¿¡æ¯ã
let callback = () => log("Regular timeout callback has run");
let urgentCallback = () => log("*** Oh noes! An urgent callback has run!");
log("Main program started");
setTimeout(callback, 0);
queueMicrotask(urgentCallback);
log("Main program exiting");
ç»æ
å¯ä»¥æ³¨æå°ï¼ä»ä¸»ç¨åºä½ä¸è¾åºçæ¥å¿é¦å åºç°ï¼æ¥ä¸æ¥æ¯å¾®ä»»å¡ä¸çè¾åºï¼å ¶åæ¯ timeout çåè°ãè¿æ¯å 为å½å¤ç主ç¨åºè¿è¡çä»»å¡éåºåï¼å¾®ä»»å¡éåå äº timeout åè°æå¨çä»»å¡éå被å¤çãè¦è®°ä½ä»»å¡å微任塿¯ä¿æåèªç¬ç«çéåçï¼ä¸å¾®ä»»å¡å æ§è¡æå©äºä¿æè¿ä¸ç¹ã
æ¥èªå½æ°ç微任å¡è¿ä¸ªä¾åéè¿å¢å ä¸ä¸ªå®æåæ ·å·¥ä½ç彿°ï¼ç¥å¾®å°æ©å±äºåä¸ä¸ªä¾åãè¯¥å½æ°ä½¿ç¨ queueMicrotask()
è°åº¦ä¸ä¸ªå¾®ä»»å¡ãæ¤ä¾çéè¦ä¹å¤æ¯å¾®ä»»å¡ä¸å¨å
¶æå¤ç彿°éåºæ¶ï¼èæ¯å¨ä¸»ç¨åºéåºæ¶è¢«æ§è¡ã
let logElem = document.getElementById("log");
let log = (s) => (logElem.innerHTML += s + "<br>");
以䏿¯ä¸»ç¨åºä»£ç ãè¿éç doWork()
彿°è°ç¨äº queueMicrotask()
ï¼ä½å¾®ä»»å¡ä»å¨æ´ä¸ªç¨åºéåºæ¶æè§¦åï¼å ä¸ºé£ææ¯ä»»å¡éåºèæ§è¡æ ä¸ä¸ºç©ºçæ¶å»ã
let callback = () => log("Regular timeout callback has run");
let urgentCallback = () => log("*** Oh noes! An urgent callback has run!");
let doWork = () => {
let result = 1;
queueMicrotask(urgentCallback);
for (let i = 2; i <= 10; i++) {
result *= i;
}
return result;
};
log("Main program started");
setTimeout(callback, 0);
log(`10! equals ${doWork()}`);
log("Main program exiting");
ç»æ åè§
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4