æ³è±¡ä¸ä¸ï¼ä½ æ¯ä¸ä½é¡¶å°ææï¼ç²ä¸æ²¡æ¥æ²¡å¤å°è¯¢é®ä½ ä¸é¦æä»ä¹æ¶ååã
为äºä»ä¸è§£æ¾ï¼ä½ æ¿è¯ºï¼promiseï¼ä¼å¨åæ²åå¸çç¬¬ä¸æ¶é´åç»ä»ä»¬ãä½ ç»äºç²ä¸ä»¬ä¸ä¸ªå表ãä»ä»¬å¯ä»¥å¨ä¸é¢å¡«åä»ä»¬ççµåé®ä»¶å°åï¼ä»¥ä¾¿å½ææ²åå¸åï¼è®©ææè®¢é äºç人è½å¤ç«å³æ¶å°ãå³ä¾¿éå°ä¸æµï¼ä¾å¦å½é³å®¤åçäºç«ç¾ï¼ä»¥è´ä½ æ æ³å叿°æï¼ä»ä»¬ä¹è½åæ¶æ¶å°ç¸å ³éç¥ã
æ¯ä¸ªäººé½å¾å¼å¿ï¼ä½ ä¸ä¼è¢«ä»»ä½äººå¬ä¿ï¼ç²ä¸ä»¬ä¹ä¸ç¨æ å¿éè¿ææ²åè¡ã
è¿æ¯æä»¬å¨ç¼ç¨ä¸ç»å¸¸éå°çäºå¿ä¸çå®çæ´»çç±»æ¯ï¼
- âç产è 代ç ï¼producing codeï¼âä¼åä¸äºäºå¿ï¼å¹¶ä¸ä¼éè¦ä¸äºæ¶é´ãä¾å¦ï¼éè¿ç½ç»å è½½æ°æ®ç代ç ãå®å°±åä¸ä½âææâã
- âæ¶è´¹è 代ç ï¼consuming codeï¼âæ³è¦å¨âç产è 代ç â宿工ä½çç¬¬ä¸æ¶é´å°±è½è·å¾å ¶å·¥ä½ææã许å¤å½æ°å¯è½é½éè¦è¿ä¸ªç»æãè¿äºå°±æ¯âç²ä¸âã
- Promise æ¯å°âç产è 代ç âåâæ¶è´¹è 代ç âè¿æ¥å¨ä¸èµ·çä¸ä¸ªç¹æ®ç JavaScript 对象ãç¨æä»¬çç±»æ¯æ¥è¯´ï¼è¿å°±æ¯å°±åæ¯â订é å表âãâç产è 代ç âè±è´¹å®æéçä»»æé¿åº¦æ¶é´æ¥äº§åºææ¿è¯ºçç»æï¼è âpromiseâ å°å¨å®ï¼è¯æ³¨ï¼æçæ¯âç产è 代ç âï¼ä¹å°±æ¯ä¸ææè¯´ç executorï¼åå¤å¥½æ¶ï¼å°ç»æåææè®¢é äºç代ç 弿¾ã
è¿ç§ç±»æ¯å¹¶ä¸åååç¡®ï¼å 为 JavaScript ç promise æ¯ç®åç订é å表æ´å 夿ï¼å®ä»¬è¿æ¥æå ¶ä»çåè½åå±éæ§ãä½ä»¥æ¤å¼å§æºå¥½çã
Promise 对象çæé å¨ï¼constructorï¼è¯æ³å¦ä¸ï¼
let promise = new Promise(function(resolve, reject) {
// executorï¼ç产è
代ç ï¼âææâï¼
});
ä¼ éç» new Promise ç彿°è¢«ç§°ä¸º executorãå½ new Promise 被å建ï¼executor ä¼èªå¨è¿è¡ãå®å
嫿ç»åºäº§åºç»æçç产è
代ç ãæç
§ä¸é¢çç±»æ¯ï¼executor å°±æ¯âææâã
å®çåæ° resolve å reject æ¯ç± JavaScript èªèº«æä¾çåè°ãæä»¬ç代ç ä»
å¨ executor çå
é¨ã
å½ executor è·å¾äºç»æï¼æ è®ºæ¯æ©è¿æ¯æé½æ²¡å ³ç³»ï¼å®åºè¯¥è°ç¨ä»¥ä¸åè°ä¹ä¸ï¼
resolve(value)ââ 妿任塿å宿并另æç»ævalueãreject(error)ââ 妿åºç°äº errorï¼errorå³ä¸º error 对象ã
æä»¥æ»ç»ä¸ä¸å°±æ¯ï¼executor ä¼èªå¨è¿è¡å¹¶å°è¯æ§è¡ä¸é¡¹å·¥ä½ãå°è¯ç»æåï¼å¦ææååè°ç¨ resolveï¼å¦æåºç° error åè°ç¨ rejectã
ç± new Promise æé å¨è¿åç promise 对象å
·æä»¥ä¸å
é¨å±æ§ï¼
stateââ æåæ¯"pending"ï¼ç¶åå¨resolve被è°ç¨æ¶å为"fulfilled"ï¼æè å¨reject被è°ç¨æ¶å为"rejected"ãresultââ æåæ¯undefinedï¼ç¶åå¨resolve(value)被è°ç¨æ¶å为valueï¼æè å¨reject(error)被è°ç¨æ¶å为errorã
æä»¥ï¼executor æç»å° promise ç§»è³ä»¥ä¸ç¶æä¹ä¸ï¼
ç¨åæä»¬å°çå°âç²ä¸âå¦ä½è®¢é è¿äºæ´æ¹ã
ä¸é¢æ¯ä¸ä¸ª promise æé å¨åä¸ä¸ªç®åç executor 彿°ï¼è¯¥ executor 彿°å
·æå
嫿¶é´ï¼å³ setTimeoutï¼çâç产è
代ç âï¼
let promise = new Promise(function(resolve, reject) {
// å½ promise 被æé 宿æ¶ï¼èªå¨æ§è¡æ¤å½æ°
// 1 ç§åååºå·¥ä½å·²ç»è¢«å®æçä¿¡å·ï¼å¹¶å¸¦æç»æ "done"
setTimeout(() => resolve("done"), 1000);
});
éè¿è¿è¡ä¸é¢ç代ç ï¼æä»¬å¯ä»¥çå°ä¸¤ä»¶äºå¿ï¼
-
executor 被èªå¨ä¸ç«å³è°ç¨ï¼éè¿
new Promiseï¼ã -
executor æ¥åä¸¤ä¸ªåæ°ï¼
resolveårejectãè¿äºå½æ°ç± JavaScript 弿é¢å å®ä¹ï¼å æ¤æä»¬ä¸éè¦å建å®ä»¬ãæä»¬åªéè¦å¨åå¤å¥½ï¼è¯æ³¨ï¼æçæ¯ executor åå¤å¥½ï¼æ¶è°ç¨å ¶ä¸ä¹ä¸å³å¯ãç»è¿ 1 ç§çâå¤çâåï¼executor è°ç¨
resolve("done")æ¥äº§çç»æãè¿å°æ¹åpromise对象çç¶æï¼
è¿æ¯ä¸ä¸ªæå宿任å¡çä¾åï¼ä¸ä¸ªâæåå®ç°äºç诺è¨âã
ä¸é¢åæ¯ä¸ä¸ª executor 以 error æç» promise ç示ä¾ï¼
let promise = new Promise(function(resolve, reject) {
// 1 ç§åååºå·¥ä½å·²ç»è¢«å®æçä¿¡å·ï¼å¹¶å¸¦æ error
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
对 reject(...) çè°ç¨å° promise 对象çç¶æç§»è³ "rejected"ï¼
æ»èè¨ä¹ï¼executor åºè¯¥æ§è¡ä¸é¡¹å·¥ä½ï¼é常æ¯éè¦è±è´¹ä¸äºæ¶é´çäºå¿ï¼ï¼ç¶åè°ç¨ resolve æ reject æ¥æ¹å对åºç promise 对象çç¶æã
䏿åç âpendingâ promise ç¸åï¼ä¸ä¸ª resolved æ rejected ç promise é½ä¼è¢«ç§°ä¸º âsettledâã
executor åªè½è°ç¨ä¸ä¸ª resolve æä¸ä¸ª rejectãä»»ä½ç¶æçæ´æ¹é½æ¯æç»çã
ææå
¶ä»çå对 resolve å reject çè°ç¨é½ä¼è¢«å¿½ç¥ï¼
let promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("â¦")); // 被忽ç¥
setTimeout(() => resolve("â¦")); // 被忽ç¥
});
å ³é®å°±å¨äºï¼ä¸ä¸ªç± executor 宿çå·¥ä½åªè½æä¸ä¸ªç»ææä¸ä¸ª errorã
å¹¶ä¸ï¼resolve/reject åªéè¦ä¸ä¸ªåæ°ï¼æä¸å
å«ä»»ä½åæ°ï¼ï¼å¹¶ä¸å°å¿½ç¥é¢å¤çåæ°ã
Error 对象 reject妿ä»ä¹ä¸è¥¿åºäºé®é¢ï¼executor åºè¯¥è°ç¨ rejectãè¿å¯ä»¥ä½¿ç¨ä»»ä½ç±»åçåæ°æ¥å®æï¼å°±å resolve 䏿 ·ï¼ãä½å»ºè®®ä½¿ç¨ Error å¯¹è±¡ï¼æç»§æ¿èª Error ç对象ï¼ãè¿æ ·åççç±å¾å¿«å°±ä¼æ¾èæè§ã
å®é
ä¸ï¼executor é常æ¯å¼æ¥æ§è¡æäºæä½ï¼å¹¶å¨ä¸æ®µæ¶é´åè°ç¨ resolve/rejectï¼ä½è¿ä¸æ¯å¿
é¡»çãæä»¬è¿å¯ä»¥ç«å³è°ç¨ resolve æ rejectï¼å°±åè¿æ ·ï¼
let promise = new Promise(function(resolve, reject) {
// ä¸è±æ¶é´å»åè¿é¡¹å·¥ä½
resolve(123); // ç«å³ç»åºç»æï¼123
});
ä¾å¦ï¼å½æä»¬å¼å§åä¸ä¸ªä»»å¡ï¼éååç°ä¸åé½å·²ç»å®æå¹¶å·²è¢«ç¼åæ¶ï¼å¯è½å°±ä¼åçè¿ç§æ åµã
è¿æºå¥½ãæä»¬ç«å³å°±æäºä¸ä¸ª resolved ç promiseã
state å result 齿¯å
é¨çPromise 对象ç state å result 屿§é½æ¯å
é¨çãæä»¬æ æ³ç´æ¥è®¿é®å®ä»¬ã使们å¯ä»¥å¯¹å®ä»¬ä½¿ç¨ .then/.catch/.finally æ¹æ³ãæä»¬å¨ä¸é¢å¯¹è¿äºæ¹æ³è¿è¡äºæè¿°ã
æ¶è´¹è ï¼thenï¼catch
Promise 对象å
å½çæ¯ executorï¼âç产è
代ç âæâææâï¼åæ¶è´¹å½æ°ï¼âç²ä¸âï¼ä¹é´çè¿æ¥ï¼åè
å°æ¥æ¶ç»ææ errorãå¯ä»¥éè¿ä½¿ç¨ .then å .catch æ¹æ³æ³¨åæ¶è´¹å½æ°ã
then
æéè¦æåºç¡çä¸ä¸ªå°±æ¯ .thenã
è¯æ³å¦ä¸ï¼
promise.then(
function(result) { /* handle a successful result */ },
function(error) { /* handle an error */ }
);
.then ç第ä¸ä¸ªåæ°æ¯ä¸ä¸ªå½æ°ï¼è¯¥å½æ°å°å¨ promise resolved 䏿¥æ¶å°ç»æåæ§è¡ã
.then ç第äºä¸ªåæ°ä¹æ¯ä¸ä¸ªå½æ°ï¼è¯¥å½æ°å°å¨ promise rejected 䏿¥æ¶å° error ä¿¡æ¯åæ§è¡ã
ä¾å¦ï¼ä»¥ä¸æ¯å¯¹æå resolved ç promise ååºçååºï¼
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
// resolve è¿è¡ .then ä¸ç第ä¸ä¸ªå½æ°
promise.then(
result => alert(result), // 1 ç§åæ¾ç¤º "done!"
error => alert(error) // ä¸è¿è¡
);
第ä¸ä¸ªå½æ°è¢«è¿è¡äºã
å¨ reject çæ åµä¸ï¼è¿è¡ç¬¬äºä¸ªï¼
let promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// reject è¿è¡ .then ä¸ç第äºä¸ªå½æ°
promise.then(
result => alert(result), // ä¸è¿è¡
error => alert(error) // 1 ç§åæ¾ç¤º "Error: Whoops!"
);
妿æä»¬åªå¯¹æå宿çæ
嵿å
´è¶£ï¼é£ä¹æä»¬å¯ä»¥åªä¸º .then æä¾ä¸ä¸ªå½æ°åæ°ï¼
let promise = new Promise(resolve => {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(alert); // 1 ç§åæ¾ç¤º "done!"
catch
妿æä»¬åªå¯¹ error æå
´è¶£ï¼é£ä¹æä»¬å¯ä»¥ä½¿ç¨ null ä½ä¸ºç¬¬ä¸ä¸ªåæ°ï¼.then(null, errorHandlingFunction)ãæè
æä»¬ä¹å¯ä»¥ä½¿ç¨ .catch(errorHandlingFunction)ï¼å
¶å®æ¯ä¸æ ·çï¼
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// .catch(f) ä¸ promise.then(null, f) 䏿 ·
promise.catch(alert); // 1 ç§åæ¾ç¤º "Error: Whoops!"
.catch(f) è°ç¨æ¯ .then(null, f) çå®å
¨ç模æï¼å®åªæ¯ä¸ä¸ªç®åå½¢å¼ã
æ¸ çï¼finally
å°±åå¸¸è§ try {...} catch {...} ä¸ç finally åå¥ä¸æ ·ï¼promise ä¸ä¹æ finallyã
è°ç¨ .finally(f) ç±»ä¼¼äº .then(f, f)ï¼å ä¸ºå½ promise settled æ¶ f 就伿§è¡ï¼æ 论 promise 被 resolve è¿æ¯ rejectã
finally çåè½æ¯è®¾ç½®ä¸ä¸ªå¤çç¨åºå¨åé¢çæä½å®æåï¼æ§è¡æ¸
ç/ç»ç»ã
ä¾å¦ï¼åæ¢å è½½æç¤ºå¨ï¼å ³éä¸åéè¦çè¿æ¥çã
æå®æ³è±¡ææ´¾å¯¹çç»ç»è ãæ è®ºæ´¾å¯¹æ¯å¥½æ¯åï¼æå¤å°æååå ï¼æä»¬é½éè¦ï¼æè è³å°åºè¯¥ï¼å¨å®ä¹åè¿è¡æ¸ çã
代ç å¯è½çèµ·æ¥åè¿æ ·ï¼
new Promise((resolve, reject) => {
/* åä¸äºéè¦æ¶é´çäºï¼ä¹åè°ç¨å¯è½ä¼ resolve ä¹å¯è½ä¼ reject */
})
// å¨ promise 为 settled æ¶è¿è¡ï¼æ 论æåä¸å¦
.finally(() => stop loading indicator)
// æä»¥ï¼å è½½æç¤ºå¨ï¼loading indicatorï¼å§ç»ä¼å¨æä»¬ç»§ç»ä¹å忢
.then(result => show result, err => show error)
请注æï¼finally(f) å¹¶ä¸å®å
¨æ¯ then(f,f) çå«åã
å®ä»¬ä¹é´æéè¦çåºå«ï¼
-
finallyå¤çç¨åºï¼handlerï¼æ²¡æåæ°ãå¨finallyä¸ï¼æä»¬ä¸ç¥é promise æ¯å¦æåãæ²¡å ³ç³»ï¼å 为æä»¬çä»»å¡éå¸¸æ¯æ§è¡â常è§âç宿ç¨åºï¼finalizing proceduresï¼ã请çä¸é¢çä¾åï¼å¦ä½ æè§ï¼
finallyå¤çç¨åºæ²¡æåæ°ï¼promise çç»æç±ä¸ä¸ä¸ªå¤çç¨åºå¤çã -
finallyå¤çç¨åºå°ç»ææ error âä¼ éâç»ä¸ä¸ä¸ªåéçå¤çç¨åºãä¾å¦ï¼å¨è¿ç»æè¢«ä»
finallyä¼ éç»äºthenï¼new Promise((resolve, reject) => { setTimeout(() => resolve("value"), 2000) }) .finally(() => alert("Promise ready")) // å 触å .then(result => alert(result)); // <-- .then æ¾ç¤º "value"æ£å¦æä»¬æçå°çï¼ç¬¬ä¸ä¸ª promise è¿åç
valueéè¿finallyè¢«ä¼ éç»äºä¸ä¸ä¸ªthenãè¿é常æ¹ä¾¿ï¼å 为
finally并䏿å³çå¤çä¸ä¸ª promise çç»æãå¦åæè¿°ï¼æ è®ºç»ææ¯ä»ä¹ï¼å®é½æ¯è¿è¡å¸¸è§æ¸ ççå°æ¹ãä¸é¢æ¯ä¸ä¸ª promise è¿åç»æä¸º error ç示ä¾ï¼è®©æä»¬çç宿¯å¦ä½éè¿
finallyè¢«ä¼ éç»catchçï¼new Promise((resolve, reject) => { throw new Error("error"); }) .finally(() => alert("Promise ready")) // å 触å .catch(err => alert(err)); // <-- .catch æ¾ç¤ºè¿ä¸ª error -
finallyå¤çç¨åºä¹ä¸åºè¯¥è¿åä»»ä½å 容ã妿å®è¿åäºï¼è¿åçå¼ä¼é»è®¤è¢«å¿½ç¥ãæ¤è§åçå¯ä¸ä¾å¤æ¯å½
finallyå¤çç¨åºæåº error æ¶ãæ¤æ¶è¿ä¸ª errorï¼è䏿¯ä»»ä½ä¹åçç»æï¼ä¼è¢«è½¬å°ä¸ä¸ä¸ªå¤çç¨åºã
æ»ç»ï¼
finallyå¤çç¨åºæ²¡æå¾å°åä¸ä¸ªå¤çç¨åºçç»æï¼å®æ²¡æåæ°ï¼ãèè¿ä¸ªç»æè¢«ä¼ éç»äºä¸ä¸ä¸ªåéçå¤çç¨åºã- 妿
finallyå¤çç¨åºè¿åäºä¸äºå 容ï¼é£ä¹è¿äºå 容ä¼è¢«å¿½ç¥ã - å½
finallyæåº error æ¶ï¼æ§è¡å°è½¬å°æè¿ç error çå¤çç¨åºã
妿æä»¬æ£ç¡®ä½¿ç¨ finallyï¼å°å
¶ç¨äºå¸¸è§æ¸
çï¼ï¼é£ä¹è¿äºåè½å°å¾æç¨ã
妿 promise 为 pending ç¶æï¼.then/catch/finally å¤çç¨åºï¼handlerï¼å°çå¾
å®çç»æã
ææ¶åï¼å½æä»¬åä¸ä¸ª promise æ·»å å¤çç¨åºæ¶ï¼å®å¯è½å·²ç» settled äºã
å¨è¿ç§æ åµä¸ï¼è¿äºå¤çç¨åºä¼ç«å³æ§è¡ï¼
// ä¸é¢è¿ promise å¨è¢«å建åç«å³å为 resolved ç¶æ
let promise = new Promise(resolve => resolve("done!"));
promise.then(alert); // done!ï¼ç«å»æ¾ç¤ºï¼
请注æè¿ä½¿å¾ promise æ¯ç°å®çæ´»ä¸çâ订é åè¡¨âæ¹æ¡å¼ºå¤§å¾å¤ã妿ææå·²ç»åå¸äºä»ä»¬çåæ²ï¼ç¶åæä¸ªäººå¨è®¢é å表ä¸è¿è¡äºæ³¨åï¼åä»ä»¬å¾å¯è½ä¸ä¼æ¶å°è¯¥åæ²ãå®é çæ´»ä¸ç订é å¿ é¡»å¨æ´»å¨å¼å§ä¹åè¿è¡ã
Promise åæ´å çµæ´»ãæä»¬å¯ä»¥éæ¶æ·»å å¤çç¨åºï¼handlerï¼ï¼å¦æç»æå·²ç»å¨äºï¼å®ä»¬å°±ä¼æ§è¡ã
示ä¾ï¼loadScript
æ¥ä¸æ¥ï¼è®©æä»¬çä¸ä¸å ³äº promise å¦ä½å¸®å©æä»¬ç¼å弿¥ä»£ç çæ´å¤å®é 示ä¾ã
æä»¬ä»ä¸ä¸ç« è·å¾äºç¨äºå è½½èæ¬ç loadScript 彿°ã
è¿æ¯åºäºåè°å½æ°çåä½ï¼è®°ä½å®ï¼
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(null, script);
script.onerror = () => callback(new Error(`Script load error for ${src}`));
document.head.append(script);
}
让æä»¬ç¨ promise éåå®ã
æ°å½æ° loadScript å°ä¸éè¦åè°ãåè代ä¹çæ¯ï¼å®å°å建并è¿åä¸ä¸ªå¨å è½½å®ææ¶ resolve ç promise 对象ãå¤é¨ä»£ç å¯ä»¥ä½¿ç¨ .then åå
¶æ·»å å¤çç¨åºï¼è®¢é
彿°ï¼ï¼
function loadScript(src) {
return new Promise(function(resolve, reject) {
let script = document.createElement('script');
script.src = src;
script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Script load error for ${src}`));
document.head.append(script);
});
}
ç¨æ³ï¼
let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js");
promise.then(
script => alert(`${script.src} is loaded!`),
error => alert(`Error: ${error.message}`)
);
promise.then(script => alert('Another handler...'));
æä»¬ç«å»å°±è½åç° promise ç¸è¾äºåºäºåè°ç模å¼çä¸äºå¥½å¤ï¼
| promise | callback |
|---|---|
promise å
许æä»¬æç
§èªç¶é¡ºåºè¿è¡ç¼ç ãé¦å
ï¼æä»¬è¿è¡ loadScriptï¼ä¹åï¼ç¨ .then æ¥å¤çç»æã |
å¨è°ç¨ loadScript(script, callback) æ¶ï¼æä»¬å¿
é¡»æä¸ä¸ª callback 彿°å¯ä¾ä½¿ç¨ãæ¢å¥è¯è¯´ï¼å¨è°ç¨ loadScript ä¹åï¼æä»¬å¿
é¡»ç¥éå¦ä½å¤çç»æã |
æä»¬å¯ä»¥æ ¹æ®éè¦ï¼å¨ promise ä¸å¤æ¬¡è°ç¨ .thenãæ¯æ¬¡è°ç¨ï¼æä»¬é½ä¼å¨â订é
å表â䏿·»å ä¸ä¸ªæ°çâç²ä¸âï¼ä¸ä¸ªæ°ç订é
彿°ãå¨ä¸ä¸ç« å°å¯¹æ¤å
容è¿è¡è¯¦ç»ä»ç»ï¼Promise é¾ã |
åªè½æä¸ä¸ªåè°ã |
å æ¤ï¼promise 为æä»¬æä¾äºæ´å¥½çä»£ç æµåçµæ´»æ§ãä½å ¶å®è¿ææ´å¤ç¸å ³å 容ãæä»¬å°å¨ä¸ä¸ç« çå°ã
è¯è®º
<code>æ ç¾æå ¥åªæå 个è¯ç代ç ï¼æå ¥å¤è¡ä»£ç å¯ä»¥ä½¿ç¨<pre>æ ç¾ï¼å¯¹äºè¶ è¿ 10 è¡ç代ç ï¼å»ºè®®ä½ ä½¿ç¨æ²ç®±ï¼plnkrï¼JSBinï¼codepenâ¦ï¼