摘要:語(yǔ)法該方法是的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。并把第一個(gè)改變狀態(tài)的的返回值,傳給的回調(diào)函數(shù)。等同于這段代碼會(huì)讓這個(gè)對(duì)象立即進(jìn)入狀態(tài),并將錯(cuò)誤對(duì)象傳遞給指定的回調(diào)函數(shù)。
什么是Promise?
MDN對(duì)Promise的定義:Promise對(duì)象用于異步操作,它表示一個(gè)尚未完成且預(yù)計(jì)在未來(lái)完成的異步操作。在學(xué)習(xí)Promise之前得先了解同步與異步:
JavaScript的執(zhí)行環(huán)境是單線程。所謂單線程,是指JS引擎中負(fù)責(zé)解釋和執(zhí)行JavaScript代碼的線程只有一個(gè),也就是一次只能完成一項(xiàng)任務(wù),這個(gè)任務(wù)執(zhí)行完后才能執(zhí)行下一個(gè),它會(huì)阻塞其他任務(wù)。這個(gè)任務(wù)可稱為主線程。
但實(shí)際上還有其他線程,如事件觸發(fā)線程,Ajax請(qǐng)求線程等。
同步模式,即上述所說(shuō)的單線程模式,一次只能執(zhí)行一個(gè)任務(wù),函數(shù)調(diào)用后需要等到函數(shù)執(zhí)行結(jié)束,返回執(zhí)行結(jié)果,才能進(jìn)行下一個(gè)任務(wù)。如果這個(gè)任務(wù)執(zhí)行的時(shí)間較長(zhǎng),就會(huì)導(dǎo)致線程阻塞。
var x = true; while(x); console.log("don"t carry out"); // 不會(huì)執(zhí)行
上面代碼中的while是一個(gè)死循環(huán),它會(huì)阻塞進(jìn)程,因此第三句console不會(huì)執(zhí)行。
異步:異步模式,即與同步模式相反,可以一起執(zhí)行多個(gè)任務(wù),函數(shù)調(diào)用后不會(huì)立即執(zhí)行返回執(zhí)行的結(jié)果,如果任務(wù)A需要等待,可先執(zhí)行任務(wù)B,等到任務(wù)A結(jié)果返回后繼續(xù)回調(diào)。
最常見的異步模式就是定時(shí)器的使用:
setTimeout(function() { console.log("taskA, asynchronous"); }, 0); console.log("taskB, synchronize"); //while(true); -------ouput------- taskB, synchronize taskA, asynchronous
雖然定時(shí)器延時(shí)的時(shí)間為0,但taskA還是晚于taskB執(zhí)行。這是因?yàn)槎〞r(shí)器是異步的,異步任務(wù)會(huì)再當(dāng)前腳本的所有同步任務(wù)執(zhí)行完后才會(huì)執(zhí)行。如果同步代碼中含有死循環(huán),則這個(gè)異步任務(wù)不會(huì)執(zhí)行,因?yàn)橥饺蝿?wù)阻塞了進(jìn)程。
回調(diào)函數(shù):上例中,setTimeout里的function便是回調(diào)函數(shù)??梢岳斫鉃椋海▓?zhí)行完)回調(diào)的函數(shù)。
WikiPedia對(duì)callback的定義可以理解為:回調(diào)函數(shù)是一段可執(zhí)行的代碼段,它以參數(shù)的形式傳遞給其他代碼,在其合適的時(shí)間執(zhí)行這段(回調(diào)函數(shù))的代碼?;卣{(diào)函數(shù)不僅是可以用于異步調(diào)用,一般同步的場(chǎng)景也可以用回調(diào)。在同步調(diào)用下,可能一段時(shí)間后執(zhí)行執(zhí)行或不執(zhí)行(未達(dá)到執(zhí)行的條件)
/******************同步回調(diào)******************/ var fun1 = function(callback) { //do something console.log("before callback"); (callback && typeof(callback) === "function") && callback(); console.log("after callback"); } var fun2 = function(param) { //do something var start = new Date(); while((new Date() - start) < 3000) { //delay 3s } console.log("I"m callback"); } fun1(fun2); -------output-------- before callback //after 3s I’m callback after callback
由于是同步調(diào)用,會(huì)阻塞后面的代碼,如果fun2是個(gè)死循環(huán),后面的代碼就不執(zhí)行了。
除了上面setTimeout為常見的異步回調(diào),另外常見的異步即Ajax請(qǐng)求:
/******************異步回調(diào)******************/ function request(url, param, successFun, errorFun) { $.ajax({ type: "GET", url: url, param: param, async: true, //默認(rèn)為true,即異步請(qǐng)求;false為同步請(qǐng)求 success: successFun, error: errorFun }); } request("test.html", "", function(data) { //請(qǐng)求成功后的回調(diào)函數(shù),通常是對(duì)請(qǐng)求回來(lái)的數(shù)據(jù)進(jìn)行處理 console.log("請(qǐng)求成功啦, 這是返回的數(shù)據(jù):", data); },function(error) { console.log("sorry, 請(qǐng)求失敗了, 這是失敗信息:", error); });為什么使用Promise
利用Promise改寫上面Ajax的例子:
function sendRequest(url, param) { return new Promise(function (resolve, reject) { request(url, param, resolve, reject); }); } sendRequest("test.html", "").then(function(data) { //異步操作成功后的回調(diào) console.log("請(qǐng)求成功啦, 這是返回的數(shù)據(jù):", data); }, function(error) { //異步操作失敗后的回調(diào) console.log("sorry, 請(qǐng)求失敗了, 這是失敗信息:", error); });
Promise的優(yōu)勢(shì)在于它的重鏈?zhǔn)秸{(diào)用,可以避免層層嵌套回調(diào)。如果第一次Ajax請(qǐng)求后,還可以用它的返回的結(jié)果再次請(qǐng)求
request("test1.html", "", function(data1) { console.log("第一次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data1); request("test2.html", data1, function (data2) { console.log("第二次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data2); request("test3.html", data2, function (data3) { console.log("第三次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data3); //request... 繼續(xù)請(qǐng)求 }, function(error3) { console.log("第三次請(qǐng)求失敗, 這是失敗信息:", error3); }); }, function(error2) { console.log("第二次請(qǐng)求失敗, 這是失敗信息:", error2); }); }, function(error1) { console.log("第一次請(qǐng)求失敗, 這是失敗信息:", error1); });
以上出現(xiàn)了多層調(diào)用,難以明白層級(jí)之間的關(guān)系,這就是常說(shuō)的回調(diào)地獄(Pyramid of Doom),而使用Promise,可以利用then進(jìn)行鏈?zhǔn)秸{(diào)用,將異步操作以同步操作的流程表示出來(lái)。
sendRequest("test1.html", "").then(function(data1) { console.log("第一次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data1); }).then(function(data2) { console.log("第二次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data2); }).then(function(data3) { console.log("第三次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data3); }).catch(function(error) { //用catch捕捉前面的錯(cuò)誤 console.log("sorry, 請(qǐng)求失敗了, 這是失敗信息:", error); });Promise的基本用法
Promise對(duì)象代表一個(gè)未完成、但預(yù)計(jì)將來(lái)會(huì)完成的操作。它有以下三種狀態(tài):
pending:初始值,不是fulfilled,也不是rejected
fulfilled:代表操作成功
rejected:代表操作失敗
Promise有兩種狀態(tài)改變的方式,既可以從pending轉(zhuǎn)變?yōu)閒ulfilled,也可以從pending轉(zhuǎn)變?yōu)閞ejected。一旦狀態(tài)改變,就會(huì)一直保持這個(gè)狀態(tài)。當(dāng)狀態(tài)發(fā)生變化,Promise.then綁定的函數(shù)就會(huì)被調(diào)用。
注意:Promise一旦新建就會(huì)立即執(zhí)行,無(wú)法取消。這也是它的缺點(diǎn)之一。
下面通過一個(gè)例子進(jìn)一步講解:
//構(gòu)建Promise var promise = new Promise(function (resolve, reject) { if (/* 異步操作成功 */) { resolve(data); } else { /* 異步操作失敗 */ reject(error); } });
類似構(gòu)建對(duì)象,我們使用new來(lái)構(gòu)建一個(gè)Promise。Promise接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是resolve和reject。這兩個(gè)函數(shù)就是回調(diào)函數(shù),由JavaScript引擎提供。
resolve函數(shù)的作用:在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果,作為參會(huì)素傳遞出去;
reject函數(shù)的作用:在異步操作失敗時(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤,作為參數(shù)傳遞出去。
Promise實(shí)例生成以后,可以用then方法指定resolve和reject狀態(tài)的回調(diào)函數(shù)。
promise.then(onFulfilled, onRejected); promise.then(function(data) { // do something when success }, function(error) { // do something when failure });
then方法會(huì)返回一個(gè)Promise。它有兩個(gè)參數(shù),分別為Promise從pending變?yōu)?b>fulfilled和rejected時(shí)的回調(diào)函數(shù)(第二個(gè)參數(shù)非必選)。這兩個(gè)函數(shù)都接受Promise對(duì)象傳出的值作為參數(shù)。
簡(jiǎn)單來(lái)說(shuō),then就是定義resolve和reject函數(shù)的,其resolve參數(shù)相當(dāng)于:
function resolveFun(data) { //data為promise傳出的值 }
而新建的Promise中的‘resolve(data)’,則相當(dāng)于執(zhí)行resolveFun函數(shù)。
Promise新建后就會(huì)立即執(zhí)行。而then方法中指定的回調(diào)函數(shù),將在當(dāng)前腳本所有同步任務(wù)執(zhí)行完才會(huì)執(zhí)行。如下例:
var promise = new Promise(function(resolve, reject) { console.log("before resolved"); resolve(); console.log("after resolved"); }); promise.then(function() { console.log("resolved"); }); console.log("outer"); -------output------- before resolved after resolved outer resolved
由于resolve指定的是異步操作成功后的回調(diào)函數(shù),它需要等所有的同步代碼執(zhí)行后才會(huì)執(zhí)行,因此最后打印‘resolved’
基本API語(yǔ)法:Promise.prototype.then(onFulfilled,onRejected)
對(duì)Promise添加onFulfilled和onRejected回調(diào),并返回的是一個(gè)新的Promise實(shí)例(不是原來(lái)那個(gè)Promise實(shí)例),且返回值將作為參數(shù)傳入這個(gè)新Promise的resolve函數(shù)。
因此可以使用鏈?zhǔn)綄懛āS捎谇耙粋€(gè)回調(diào)函數(shù),返回的還是一個(gè)Promise對(duì)象(即有異步操作),這時(shí)后一個(gè)回調(diào)函數(shù),就會(huì)等待該Promise對(duì)象的狀態(tài)發(fā)生變化,才會(huì)被調(diào)用。
語(yǔ)法:Promise.prototype.catch(onRejected)
該方法是.then(undefined,onRejected)的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。
promise.then(function(data) { console.log("success"); }).catch(function(error) { console.log("error", error); }); /*******等同于*******/ promise.then(function(data) { console.log("success"); }).then(undefined, function(error) { console.log("error", error); });
var promise = new Promise(function (resolve, reject) { throw new Error("test"); }); /*******等同于*******/ var promise = new Promise(function (resolve, reject) { reject(new Error("test")); }); //用catch捕獲 promise.catch(function (error) { console.log(error); }); -------output------- Error: test
從上例可知,reject方法的作用等同于拋錯(cuò)。
promise對(duì)象的錯(cuò)誤,會(huì)一直向后傳遞,直到被捕獲。即錯(cuò)誤總會(huì)被下一個(gè)catch所捕獲。then方法指定的回調(diào)函數(shù),若拋出錯(cuò)誤,也會(huì)被下一個(gè)catch捕獲。catch中也能拋錯(cuò),則需要后面的catch來(lái)捕獲。
sendRequest("test.html").then(function(data1) { //do something }).then(function (data2) { //do something }).catch(function (error) { //處理前面三個(gè)Promise產(chǎn)生的錯(cuò)誤 });
上面提到的,promise狀態(tài)一旦改變就會(huì)凝固,不會(huì)再改變。因此promise一旦fulfilled了,再拋錯(cuò),也不會(huì)變?yōu)?b>rejected,就不會(huì)被catch了
var promise = new Promise(function(resolve, reject) { resolve(); throw "error"; }); promise.catch(function(e) { console.log(e); //This is never called });
如果沒有使用catch方法指定處理錯(cuò)誤的回調(diào)函數(shù),Promise對(duì)象拋出的錯(cuò)誤不會(huì)傳遞到外層代碼,即不會(huì)有任何反應(yīng)(Chrome會(huì)拋錯(cuò)),這是Promise的另一個(gè)缺點(diǎn)。
var promise = new Promise(function (resolve, reject) { resolve(x); }); promise.then(function (data) { console.log(data); });
如圖所示,只有Chrome會(huì)拋錯(cuò),且promise狀態(tài)變?yōu)?b>rejected,Firefox和Safari中錯(cuò)誤不會(huì)被捕獲,也不會(huì)傳遞到外層代碼,最后沒有任何輸出,promise狀態(tài)也變?yōu)?b>rejected。
語(yǔ)法:Promise.all(iterable)
該方法用于將多個(gè)Promise實(shí)例,包裝成一個(gè)新的Promise實(shí)例。
var p = Promise.all([p1, p2, p3]);
Promise.all方法接受一個(gè)數(shù)組(或具有Iterator接口)作參數(shù),數(shù)組中的對(duì)象(p1,p2,p3)均為promise實(shí)例(如果不是一個(gè)promise,該項(xiàng)會(huì)被用Promise.resolve轉(zhuǎn)換為一個(gè)promise)。它的狀態(tài)由這三個(gè)promise實(shí)例來(lái)決定。
當(dāng)p1,p2,p3狀態(tài)都為fulfilled,p的狀態(tài)才會(huì)變?yōu)?b>fulfilled,并將三個(gè)promise返回的結(jié)果,按參數(shù)的順序(而不是resolved的順序)存入數(shù)組,傳給p的回調(diào)函數(shù);
/* 例3.8 */ var p1 = new Promise(function (resolve, reject) { setTimeout(resolve, 3000, "first"); }); var p2 = new Promise(function (resolve, reject) { resolve("second"); }); var p3 = new Promise((resolve, reject) => { setTimeout(resolve, 1000, "third"); }); Promise.all([p1, p2, p3]).then(function(values) { console.log(values); }); -------output------- //約 3s 后 ["first", "second", "third"]
當(dāng)p1,p2,p3其中之一狀態(tài)變?yōu)?b>rejected,p的狀態(tài)也會(huì)變?yōu)?b>rejected,并把第一個(gè)被rejected的promise的返回值,傳給p的回調(diào)函數(shù);
var p1 = new Promise((resolve, reject) => { setTimeout(resolve, 1000, "one"); }); var p2 = new Promise((resolve, reject) => { setTimeout(reject, 2000, "two"); }); var p3 = new Promise((resolve, reject) => { reject("three"); }); Promise.all([p1, p2, p3]).then(function (value) { console.log("resolve", value); }, function (error) { console.log("reject", error); // => reject three }); -------output------- reject three
這多個(gè)promise是同時(shí)開始、并行執(zhí)行的,而不是順序執(zhí)行的。
function timerPromisefy(delay) { return new Promise(function (resolve) { setTimeout(function () { resolve(delay); }, delay); }); } var startDate = Date.now(); Promise.all([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]).then(function (values) { console.log(Date.now() - startDate + "ms"); console.log(values); }); -------output------- 133ms //不一定,但大于128ms [1,32,64,128].race()
語(yǔ)法:Promise.race(iterable)
該方法同樣接受一個(gè)數(shù)組(或具有Iterator接口)作參數(shù)。當(dāng)p1,p2,p3中有一個(gè)實(shí)例的狀態(tài)發(fā)生改變(變?yōu)?b>fulfilled或rejected),p的狀態(tài)就跟著改變。并把第一個(gè)改變狀態(tài)的promise的返回值,傳給p的回調(diào)函數(shù)。
var p1 = new Promise(function(resolve, reject) { setTimeout(reject, 500, "one"); }); var p2 = new Promise(function(resolve, reject) { setTimeout(resolve, 100, "two"); }); Promise.race([p1, p2]).then(function(value) { console.log("resolve", value); }, function(error) { //not called console.log("reject", error); }); -------output------- resolve two var p3 = new Promise(function(resolve, reject) { setTimeout(resolve, 500, "three"); }); var p4 = new Promise(function(resolve, reject) { setTimeout(reject, 100, "four"); }); Promise.race([p3, p4]).then(function(value) { //not called console.log("resolve", value); }, function(error) { console.log("reject", error); }); -------output------- reject four
在第一個(gè)promise對(duì)象變?yōu)閞esolve后,并不會(huì)取消其他promise對(duì)象的執(zhí)行,如下 var fastPromise = new Promise(function (resolve) { setTimeout(function () { console.log("fastPromise"); resolve("resolve fastPromise"); }, 100); }); var slowPromise = new Promise(function (resolve) { setTimeout(function () { console.log("slowPromise"); resolve("resolve slowPromise"); }, 1000); }); // 第一個(gè)promise變?yōu)閞esolve后程序停止 Promise.race([fastPromise, slowPromise]).then(function (value) { console.log(value); // => resolve fastPromise }); -------output------- fastPromise resolve fastPromise slowPromise //仍會(huì)執(zhí)行.resolve()
語(yǔ)法:
Promise.resolve(value);
Promise.resolve(promise);
Promise.resolve(thenable);
它可以看做new Promise()的快捷方式
Promise.resolve("Success"); /*******等同于*******/ new Promise(function (resolve) { resolve("Success"); });
這段代碼會(huì)讓這個(gè)Promise對(duì)象立即進(jìn)入resolved狀態(tài),并將結(jié)果success傳遞給then指定的onFulfilled回調(diào)函數(shù)。由于Promise.resolve()也是返回Promise對(duì)象,因此可以用.then()處理其返回值。
Promise.resolve("success").then(function (value) { console.log(value); }); -------output------- success
//Resolving an array Promise.resolve([1,2,3]).then(function(value) { console.log(value[0]); // => 1 }); //Resolving a Promise var p1 = Promise.resolve("this is p1"); var p2 = Promise.resolve(p1); p2.then(function (value) { console.log(value); // => this is p1 });
Promise.resolve()的另一個(gè)作用就是將thenable對(duì)象(即帶有then的對(duì)象)轉(zhuǎn)換為promise對(duì)象。
var p1 = Promise.resolve({ then: function (resolve, reject) { resolve("this is an thenable object!"); } }); console.log(p1 instanceof Promise); // => true p1.then(function(value) { console.log(value); // => this is an thenable object! }, function(e) { //not called });
下面兩個(gè)例子,無(wú)論是在什么時(shí)候拋異常,只要promise狀態(tài)變成resolved或rejected,狀態(tài)不會(huì)再改變,這和新建promise是一樣的。
//在回調(diào)函數(shù)前拋異常 var p1 = { then: function(resolve) { throw new Error("error"); resolve("Resolved"); } }; var p2 = Promise.resolve(p1); p2.then(function(value) { //not called }, function(error) { console.log(error); // => Error: error }); //在回調(diào)函數(shù)后拋異常 var p3 = { then: function(resolve) { resolve("Resolved"); throw new Error("error"); } }; var p4 = Promise.resolve(p3); p4.then(function(value) { console.log(value); // => Resolved }, function(error) { //not called });.reject()
語(yǔ)法:Promise.reject(reason)
這個(gè)方法和上述的Promise.resolve()類似,它也是new Promise()的快捷方式。
Promise.reject(new Error("error")); /*******等同于*******/ new Promise(function (resolve, reject) { reject(new Error("error")); });
這段代碼會(huì)讓這個(gè)Promise對(duì)象立即進(jìn)入rejected狀態(tài),并將錯(cuò)誤對(duì)象傳遞給then指定的onRejected回調(diào)函數(shù)。
Promise常見問題 總結(jié)一下創(chuàng)建promise的流程:使用new Promise(fn)或者它的快捷方式Promise.resolve()、Promise.reject(),返回一個(gè)promise對(duì)象
在fn中指定異步的處理
處理結(jié)果正常,調(diào)用resolve
處理結(jié)果錯(cuò)誤,調(diào)用reject
如果使用ES6的箭頭函數(shù),將會(huì)使寫法更加簡(jiǎn)單清晰
接下來(lái)用例子說(shuō)明promise使用過程中的注意點(diǎn)及容易犯的錯(cuò)誤。
promise.then(onFulfilled,onRejected) 在onFulfilled中發(fā)生異常的話,在onRejected中是捕獲不到這個(gè)異常的。
promise.then(onFilfilled).catch(onRejected) .then中產(chǎn)生的異常能在.catch中捕獲。
一般情況,使用第二種,第二種的.catch()也可以使用.then()表示,它們本質(zhì)上沒有區(qū)別,.catch===.then(null,onRejected)
情景2:如果在then中拋錯(cuò),而沒有對(duì)錯(cuò)進(jìn)行處理(即catch),那么會(huì)一直保持reject狀態(tài),直到catch了錯(cuò)誤。
function taskA() { console.log(x); console.log("Task A"); } function taskB() { console.log("Task B"); } function onRejected(error) { console.log("Catch Error: A or B", error); } function finalTask() { console.log("Final Task"); } var promise = Promise.resolve(); promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask); -------output------- Catch Error: A or B,ReferenceError: x is not defined Final Task
從代碼的輸出結(jié)果及流程,可以看出,A拋錯(cuò)時(shí),會(huì)按照taskA->onRejected->finalTask這個(gè)流程來(lái)處理。A拋錯(cuò)后,若沒有對(duì)它進(jìn)行處理,狀態(tài)就會(huì)維持rejected,taskB不會(huì)執(zhí)行,直到catch了錯(cuò)誤。
function taskA() { console.log(x); console.log("Task A"); } function taskB() { console.log("Task B"); } function onRejectedA(error) { console.log("Catch Error: A", error); } function onRejectedB(error) { console.log("Catch Error: B", error); } function finalTask() { console.log("Final Task"); } var promise = Promise.resolve(); promise .then(taskA) .catch(onRejectedA) .then(taskB) .catch(onRejectedB) .then(finalTask); -------output------- Catch Error: A ReferenceError: x is not defined Task B Final Task
在TaskA后多了對(duì)A的處理,因此,A拋錯(cuò)時(shí),會(huì)按照taskA->onRejectedA->taskB->finalTask這個(gè)流程來(lái)處理,此時(shí)taskB是正常執(zhí)行的。
情景3:每次調(diào)用then都會(huì)返回一個(gè)新創(chuàng)建的promise對(duì)象,而then內(nèi)部只是返回了數(shù)據(jù)。
//方法1:對(duì)同一個(gè)promise對(duì)象同時(shí)調(diào)用 then 方法 var p1 = new Promise(function (resolve) { resolve(100); }); p1.then(function (value) { return value * 2; }); p1.then(function (value) { return value * 2; }); p1.then(function (value) { console.log("finally: " + value); }); -------output------- finally: 100 //方法2:對(duì) then 進(jìn)行 promise chain 方式進(jìn)行調(diào)用 var p2 = new Promise(function (resolve) { resolve(100); }); p2.then(function (value) { return value * 2; }).then(function (value) { return value * 2; }).then(function (value) { console.log("finally: " + value); }); -------output------- finally: 400
第一種方法中,then的調(diào)用幾乎是同時(shí)開始執(zhí)行的,且傳給每個(gè)then的value都是100,這種方法應(yīng)當(dāng)避免。方法二才是正確的鏈?zhǔn)秸{(diào)用。
容易出現(xiàn)下面的錯(cuò)誤寫法:
function badAsyncCall(data) { var promise = Promise.resolve(data); promise.then(function(value) { //do something return value + 1; }); return promise; } badAsyncCall(10).then(function(value) { console.log(value); //想要得到11,實(shí)際輸出10 }); -------output------- 10
正確的寫法:
function goodAsyncCall(data) { var promise = Promise.resolve(data); return promise.then(function(value) { //do something return value + 1; }); } goodAsyncCall(10).then(function(value) { console.log(value); }); -------output------- 11情景4:在異步回調(diào)中拋錯(cuò),不會(huì)被catch到
// Errors thrown inside asynchronous functions will act like uncaught errors var promise = new Promise(function(resolve, reject) { setTimeout(function() { throw "Uncaught Exception!"; }, 1000); }); promise.catch(function(e) { console.log(e); //This is never called });情景5:
promise狀態(tài)變?yōu)?b>resolve或reject,就凝固了,不會(huì)再改變
console.log(1); new Promise(function (resolve, reject){ reject(); setTimeout(function (){ resolve(); //not called }, 0); }).then(function(){ console.log(2); }, function(){ console.log(3); }); console.log(4); -------output------- 1 4 3
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/101106.html
摘要:下一篇大概就是源碼方面的學(xué)習(xí)筆記了龜速學(xué)習(xí)中這一次我是去看了下規(guī)范照例傳送門圖靈社區(qū)規(guī)范首先吧個(gè)人總結(jié)下該用的詞解決結(jié)婚拒絕婉拒終值值傳家寶拒因好人卡等等異常車禍理下概念我們的的就像是一場(chǎng)姻緣對(duì)吧解決呢就是結(jié)婚成功啦傳家寶也如愿的傳給下一代 下一篇大概就是源碼方面的學(xué)習(xí)筆記了...龜速學(xué)習(xí)中... 這一次我是去看了下Promises/A+規(guī)范照例傳送門:圖靈社區(qū)Promises/A+規(guī)...
摘要:版本以及之前,本身還沒有異步執(zhí)行代碼的能力,宿主環(huán)境傳遞給引擎,然后按順序執(zhí)行,由宿主發(fā)起任務(wù)。采納引擎術(shù)語(yǔ),把宿主發(fā)起的任務(wù)稱為宏觀任務(wù),把引擎發(fā)起的任務(wù)稱為微觀任務(wù)?;居梅ㄊ纠幕卣{(diào)是一個(gè)異步的執(zhí)行過程。 筆記說(shuō)明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過程的一些要點(diǎn)筆記以及感悟,完整的...
摘要:版本以及之前,本身還沒有異步執(zhí)行代碼的能力,宿主環(huán)境傳遞給引擎,然后按順序執(zhí)行,由宿主發(fā)起任務(wù)。采納引擎術(shù)語(yǔ),把宿主發(fā)起的任務(wù)稱為宏觀任務(wù),把引擎發(fā)起的任務(wù)稱為微觀任務(wù)?;居梅ㄊ纠幕卣{(diào)是一個(gè)異步的執(zhí)行過程。 筆記說(shuō)明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過程的一些要點(diǎn)筆記以及感悟,完整的...
摘要:版本以及之前,本身還沒有異步執(zhí)行代碼的能力,宿主環(huán)境傳遞給引擎,然后按順序執(zhí)行,由宿主發(fā)起任務(wù)。采納引擎術(shù)語(yǔ),把宿主發(fā)起的任務(wù)稱為宏觀任務(wù),把引擎發(fā)起的任務(wù)稱為微觀任務(wù)。基本用法示例的回調(diào)是一個(gè)異步的執(zhí)行過程。 筆記說(shuō)明 重學(xué)前端是程劭非(winter)【前手機(jī)淘寶前端負(fù)責(zé)人】在極客時(shí)間開的一個(gè)專欄,每天10分鐘,重構(gòu)你的前端知識(shí)體系,筆者主要整理學(xué)習(xí)過程的一些要點(diǎn)筆記以及感悟,完整的...
摘要:異步操作未完成異步操作成功異步操作失敗基本用法是一個(gè)構(gòu)造函數(shù),接收一個(gè)參數(shù),這個(gè)參數(shù)是函數(shù),同時(shí)這個(gè)參數(shù)函數(shù)要傳入兩個(gè)參數(shù),,分別表示異步操作執(zhí)行成功后的回調(diào)函數(shù)和異步操作執(zhí)行失敗后的回調(diào)函數(shù)。如果調(diào)用函數(shù),就會(huì)調(diào)用方法的第一個(gè)參數(shù)。 Promise對(duì)象 Promise 表示一個(gè)異步操作的最終結(jié)果,與之進(jìn)行交互的方式主要是 then 方法,該方法注冊(cè)了兩個(gè)回調(diào)函數(shù),用于接收 promi...
閱讀 853·2021-11-24 09:38
閱讀 1085·2021-10-08 10:05
閱讀 2577·2021-09-10 11:21
閱讀 2800·2019-08-30 15:53
閱讀 1827·2019-08-30 15:52
閱讀 1964·2019-08-29 12:17
閱讀 3418·2019-08-29 11:21
閱讀 1609·2019-08-26 12:17