本文主要對ES6的Promise
進行一些入門級的介紹。要想學習一個知識點,確定是從三個方面出發,what、why、how。下面就跟着我一步步學習吧~javascript
首先是what。那麼什麼是Promise
呢?
如下是MDN對Promise
的定義css
The Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that hasn't completed yet, but is expected in the future.譯文:Promise對象用於異步操做,它表示一個還沒有完成且預計在將來完成的異步操做。html
那麼什麼是異步操做?在學習promise以前須要把這個概念搞明白,下面將抽離一章專門介紹。java
咱們知道,JavaScript的執行環境是「單線程」。
所謂單線程,是指JS引擎中負責解釋和執行JavaScript代碼的線程只有一個,也就是一次只能完成一項任務,這個任務執行完後才能執行下一個,它會「阻塞」其餘任務。這個任務可稱爲主線程。
但實際上還有其餘線程,如事件觸發線程、ajax請求線程等。ajax
這也就引起了同步和異步的問題。typescript
同步模式,即上述所說的單線程模式,一次只能執行一個任務,函數調用後需等到函數執行結束,返回執行的結果,才能進行下一個任務。若是這個任務執行的時間較長,就會致使「線程阻塞」。編程
1 /* 例2.1 */ 2 var x = true; 3 while(x); 4 console.log("don't carry out"); //不會執行
上面的例子即同步模式,其中的while是一個死循環,它會阻塞進程,所以第三句console不會執行。
同步模式比較簡單,也較容易編寫。但問題也顯而易見,若是請求的時間較長,而阻塞了後面代碼的執行,體驗是很很差的。所以對於一些耗時的操做,異步模式則是更好的選擇。數組
下面就來看看異步模式。
異步模式,即與同步模式相反,能夠一塊兒執行多個任務,函數調用後不會當即返回執行的結果,若是任務A須要等待,可先執行任務B,等到任務A結果返回後再繼續回調。
最多見的異步模式就數定時器了,咱們來看看如下的例子。promise
1 /* 例2.2 */ 2 setTimeout(function() { 3 console.log('taskA, asynchronous'); 4 }, 0); 5 console.log('taskB, synchronize'); 6 //while(true); 7 8 -------ouput------- 9 taskB, synchronize 10 taskA, asynchronous
咱們能夠看到,定時器延時的時間明明爲0,但taskA仍是晚於taskB執行。這是爲何呢?因爲定時器是異步的,異步任務會在當前腳本的全部同步任務執行完纔會執行。若是同步代碼中含有死循環,即將上例的註釋去掉,那麼這個異步任務就不會執行,由於同步任務阻塞了進程。app
提起異步,就不得不談談回調函數了。上例中,setTimeout
裏的function
即是回調函數。能夠簡單理解爲:(執行完)回(來)調(用)的函數。
如下是WikiPedia對於callback
的定義。
In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time.
能夠看出,回調函數是一段可執行的代碼段,它以「參數」的形式傳遞給其餘代碼,在其合適的時間執行這段(回調函數)的代碼。
WikiPedia同時提到
The invocation may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback.
也就是說,回調函數不只能夠用於異步調用,通常同步的場景也能夠用回調。在同步調用下,回調函數通常是最後執行的。而異步調用下,可能一段時間後執行或不執行(未達到執行的條件)。
1 /* 例2.3 */ 2 /******************同步回調******************/ 3 var fun1 = function(callback) { 4 //do something 5 console.log("before callback"); 6 (callback && typeof(callback) === 'function') && callback(); 7 console.log("after callback"); 8 } 9 var fun2 = function(param) { 10 //do something 11 var start = new Date(); 12 while((new Date() - start) < 3000) { //delay 3s 13 } 14 console.log("I'm callback"); 15 } 16 fun1(fun2); 17 18 -------output-------- 19 before callback 20 //after 3s 21 I’m callback 22 after callback
因爲是同步回調,會阻塞後面的代碼,若是fun2是個死循環,後面的代碼就不執行了。
上一小節中setTimeout
就是常見的異步回調,另外常見的異步回調即ajax請求。
1 /* 例2.4 */ 2 /******************異步回調******************/ 3 function request(url, param, successFun, errorFun) { 4 $.ajax({ 5 type: 'GET', 6 url: url, 7 param: param, 8 async: true, //默認爲true,即異步請求;false爲同步請求 9 success: successFun, 10 error: errorFun 11 }); 12 } 13 request('test.html', '', function(data) { 14 //請求成功後的回調函數,一般是對請求回來的數據進行處理 15 console.log('請求成功啦, 這是返回的數據:', data); 16 },function(error) { 17 console.log('sorry, 請求失敗了, 這是失敗信息:', error); 18 });
說完了以上基本概念,咱們就能夠繼續學習Promise
了。
上面提到,Promise
對象是用於異步操做的。既然咱們可使用異步回調來進行異步操做,爲何還要引入一個Promise
新概念,還要花時間學習它呢?不要着急,下面就來談談Promise
的過人之處。
咱們先看看下面的demo,利用Promise
改寫例2.4的異步回調。
1 /* 例2.5 */ 2 function sendRequest(url, param) { 3 return new Promise(function (resolve, reject) { 4 request(url, param, resolve, reject); 5 }); 6 } 7 8 sendRequest('test.html', '').then(function(data) { 9 //異步操做成功後的回調 10 console.log('請求成功啦, 這是返回的數據:', data); 11 }, function(error) { 12 //異步操做失敗後的回調 13 console.log('sorry, 請求失敗了, 這是失敗信息:', error); 14 });
這麼一看,並無什麼區別,還比上面的異步回調複雜,得先新建Promise再定義其回調。其實,Promise
的真正強大之處在於它的多重鏈式調用,能夠避免層層嵌套回調。若是咱們在第一次ajax請求後,還要用它返回的結果再次請求呢?
1 /* 例2.6 */ 2 request('test1.html', '', function(data1) { 3 console.log('第一次請求成功, 這是返回的數據:', data1); 4 request('test2.html', data1, function (data2) { 5 console.log('第二次請求成功, 這是返回的數據:', data2); 6 request('test3.html', data2, function (data3) { 7 console.log('第三次請求成功, 這是返回的數據:', data3); 8 //request... 繼續請求 9 }, function(error3) { 10 console.log('第三次請求失敗, 這是失敗信息:', error3); 11 }); 12 }, function(error2) { 13 console.log('第二次請求失敗, 這是失敗信息:', error2); 14 }); 15 }, function(error1) { 16 console.log('第一次請求失敗, 這是失敗信息:', error1); 17 });
以上出現了多層回調嵌套,有種暈頭轉向的感受。這也就是咱們常說的厄運回調金字塔(Pyramid of Doom),編程體驗十分很差。而使用Promise
,咱們就能夠利用then
進行「鏈式回調」,將異步操做以同步操做的流程表示出來。
1 /* 例2.7 */ 2 sendRequest('test1.html', '').then(function(data1) { 3 console.log('第一次請求成功, 這是返回的數據:', data1); 4 }).then(function(data2) { 5 console.log('第二次請求成功, 這是返回的數據:', data2); 6 }).then(function(data3) { 7 console.log('第三次請求成功, 這是返回的數據:', data3); 8 }).catch(function(error) { 9 //用catch捕捉前面的錯誤 10 console.log('sorry, 請求失敗了, 這是失敗信息:', error); 11 });
是否是明顯清晰不少?孰優孰略也無需多說了吧~下面就讓咱們真正進入Promise
的學習。
上一小節咱們認識了promise
長什麼樣,但對它用到的resolve
、reject
、then
、catch
想必還不理解。下面咱們一步步學習。
Promise
對象表明一個未完成、但預計未來會完成的操做。
它有如下三種狀態:
pending
:初始值,不是fulfilled,也不是rejectedfulfilled
:表明操做成功rejected
:表明操做失敗Promise
有兩種狀態改變的方式,既能夠從pending
轉變爲fulfilled
,也能夠從pending
轉變爲rejected
。一旦狀態改變,就「凝固」了,會一直保持這個狀態,不會再發生變化。當狀態發生變化,promise.then
綁定的函數就會被調用。
注意:Promise
一旦新建就會「當即執行」,沒法取消。這也是它的缺點之一。
下面就經過例子進一步講解。
1 /* 例3.1 */ 2 //構建Promise 3 var promise = new Promise(function (resolve, reject) { 4 if (/* 異步操做成功 */) { 5 resolve(data); 6 } else { 7 /* 異步操做失敗 */ 8 reject(error); 9 } 10 });
相似構建對象,咱們使用new
來構建一個Promise
。Promise
接受一個「函數」做爲參數,該函數的兩個參數分別是resolve
和reject
。這兩個函數就是就是「回調函數」,由JavaScript引擎提供。
resolve
函數的做用:在異步操做成功時調用,並將異步操做的結果,做爲參數傳遞出去; reject
函數的做用:在異步操做失敗時調用,並將異步操做報出的錯誤,做爲參數傳遞出去。
Promise實例生成之後,能夠用then
方法指定resolved
狀態和reject
狀態的回調函數。
1 /* 接例3.1 */ 2 promise.then(onFulfilled, onRejected); 3 4 promise.then(function(data) { 5 // do something when success 6 }, function(error) { 7 // do something when failure 8 });
then
方法會返回一個Promise。它有兩個參數,分別爲Promise從pending
變爲fulfilled
和rejected
時的回調函數(第二個參數非必選)。這兩個函數都接受Promise對象傳出的值做爲參數。
簡單來講,then
就是定義resolve
和reject
函數的,其resolve
參數至關於:
1 function resolveFun(data) { 2 //data爲promise傳出的值 3 }
而新建Promise中的'resolve(data)',則至關於執行resolveFun函數。
Promise新建後就會當即執行。而then
方法中指定的回調函數,將在當前腳本全部同步任務執行完纔會執行。以下例:
1 /* 例3.2 */ 2 var promise = new Promise(function(resolve, reject) { 3 console.log('before resolved'); 4 resolve(); 5 console.log('after resolved'); 6 }); 7 8 promise.then(function() { 9 console.log('resolved'); 10 }); 11 12 console.log('outer'); 13 14 -------output------- 15 before resolved 16 after resolved 17 outer 18 resolved
因爲resolve
指定的是異步操做成功後的回調函數,它須要等全部同步代碼執行後纔會執行,所以最後打印'resolved',這個和例2.2是同樣的道理。
語法:Promise.prototype.then(onFulfilled, onRejected)
對promise添加onFulfilled
和onRejected
回調,並返回的是一個新的Promise實例(不是原來那個Promise實例),且返回值將做爲參數傳入這個新Promise的resolve
函數。
所以,咱們可使用鏈式寫法,如上文的例2.7。因爲前一個回調函數,返回的仍是一個Promise對象(即有異步操做),這時後一個回調函數,就會等待該Promise對象的狀態發生變化,纔會被調用。
語法:Promise.prototype.catch(onRejected)
該方法是.then(undefined, onRejected)
的別名,用於指定發生錯誤時的回調函數。
1 /* 例3.3 */ 2 promise.then(function(data) { 3 console.log('success'); 4 }).catch(function(error) { 5 console.log('error', error); 6 }); 7 8 /*******等同於*******/ 9 promise.then(function(data) { 10 console.log('success'); 11 }).then(undefined, function(error) { 12 console.log('error', error); 13 });
1 /* 例3.4 */ 2 var promise = new Promise(function (resolve, reject) { 3 throw new Error('test'); 4 }); 5 /*******等同於*******/ 6 var promise = new Promise(function (resolve, reject) { 7 reject(new Error('test')); 8 }); 9 10 //用catch捕獲 11 promise.catch(function (error) { 12 console.log(error); 13 }); 14 -------output------- 15 Error: test
從上例能夠看出,reject
方法的做用,等同於拋錯。
promise對象的錯誤,會一直向後傳遞,直到被捕獲。即錯誤總會被下一個catch
所捕獲。then
方法指定的回調函數,若拋出錯誤,也會被下一個catch
捕獲。catch
中也能拋錯,則須要後面的catch
來捕獲。
1 /* 例3.5 */ 2 sendRequest('test.html').then(function(data1) { 3 //do something 4 }).then(function (data2) { 5 //do something 6 }).catch(function (error) { 7 //處理前面三個Promise產生的錯誤 8 });
上文提到過,promise狀態一旦改變就會凝固,不會再改變。所以promise一旦fulfilled
了,再拋錯,也不會變爲rejected
,就不會被catch
了。
1 /* 例3.6 */ 2 var promise = new Promise(function(resolve, reject) { 3 resolve(); 4 throw 'error'; 5 }); 6 7 promise.catch(function(e) { 8 console.log(e); //This is never called 9 });
若是沒有使用catch
方法指定處理錯誤的回調函數,Promise對象拋出的錯誤不會傳遞到外層代碼,即不會有任何反應(Chrome會拋錯),這是Promise的另外一個缺點。
1 /* 例3.7 */ 2 var promise = new Promise(function (resolve, reject) { 3 resolve(x); 4 }); 5 promise.then(function (data) { 6 console.log(data); 7 });
如圖所示,只有Chrome會拋錯,且promise狀態變爲rejected
,Firefox和Safari中錯誤不會被捕獲,也不會傳遞到外層代碼,最後沒有任何輸出,promise狀態也變爲rejected
。
語法:Promise.all(iterable)
該方法用於將多個Promise實例,包裝成一個新的Promise實例。
var p = Promise.all([p1, p2, p3]);
Promise.all
方法接受一個數組(或具備Iterator接口)做參數,數組中的對象(p一、p二、p3)均爲promise實例(若是不是一個promise,該項會被用Promise.resolve
轉換爲一個promise)。它的狀態由這三個promise實例決定。
fulfilled
,p的狀態纔會變爲fulfilled
,並將三個promise返回的結果,按參數的順序(而不是 resolved
的順序)存入數組,傳給p的回調函數,如例3.8。rejected
,p的狀態也會變爲rejected
,並把第一個被reject
的promise的返回值,傳給p的回調函數,如例3.9。1 /* 例3.8 */ 2 var p1 = new Promise(function (resolve, reject) { 3 setTimeout(resolve, 3000, "first"); 4 }); 5 var p2 = new Promise(function (resolve, reject) { 6 resolve('second'); 7 }); 8 var p3 = new Promise((resolve, reject) => { 9 setTimeout(resolve, 1000, "third"); 10 }); 11 12 Promise.all([p1, p2, p3]).then(function(values) { 13 console.log(values); 14 }); 15 16 -------output------- 17 //約 3s 後 18 ["first", "second", "third"]
1 /* 例3.9 */ 2 var p1 = new Promise((resolve, reject) => { 3 setTimeout(resolve, 1000, "one"); 4 }); 5 var p2 = new Promise((resolve, reject) => { 6 setTimeout(reject, 2000, "two"); 7 }); 8 var p3 = new Promise((resolve, reject) => { 9 reject("three"); 10 }); 11 12 Promise.all([p1, p2, p3]).then(function (value) { 13 console.log('resolve', value); 14 }, function (error) { 15 console.log('reject', error); // => reject three 16 }); 17 18 -------output------- 19 reject three
這多個 promise 是同時開始、並行執行的,而不是順序執行。從下面例子能夠看出。若是一個個執行,那至少須要 1+32+64+128
1 /* 例3.10 */ 2 function timerPromisefy(delay) { 3 return new Promise(function (resolve) { 4 setTimeout(function () { 5 resolve(delay); 6 }, delay); 7 }); 8 } 9 var startDate = Date.now(); 10 11 Promise.all([ 12 timerPromisefy(1), 13 timerPromisefy(32), 14 timerPromisefy(64), 15 timerPromisefy(128) 16 ]).then(function (values) { 17 console.log(Date.now() - startDate + 'ms'); 18 console.log(values); 19 }); 20 -------output------- 21 133ms //不必定,但大於128ms 22 [1,32,64,128]
語法:Promise.race(iterable)
該方法一樣是將多個Promise實例,包裝成一個新的Promise實例。
var p = Promise.race([p1, p2, p3]);
Promise.race
方法一樣接受一個數組(或具備Iterator接口)做參數。當p1, p2, p3中有一個實例的狀態發生改變(變爲fulfilled
或rejected
),p的狀態就跟着改變。並把第一個改變狀態的promise的返回值,傳給p的回調函數。
1 /* 例3.11 */ 2 var p1 = new Promise(function(resolve, reject) { 3 setTimeout(reject, 500, "one"); 4 }); 5 var p2 = new Promise(function(resolve, reject) { 6 setTimeout(resolve, 100, "two"); 7 }); 8 9 Promise.race([p1, p2]).then(function(value) { 10 console.log('resolve', value); 11 }, function(error) { 12 //not called 13 console.log('reject', error); 14 }); 15 -------output------- 16 resolve two 17 18 var p3 = new Promise(function(resolve, reject) { 19 setTimeout(resolve, 500, "three"); 20 }); 21 var p4 = new Promise(function(resolve, reject) { 22 setTimeout(reject, 100, "four"); 23 }); 24 25 Promise.race([p3, p4]).then(function(value) { 26 //not called 27 console.log('resolve', value); 28 }, function(error) { 29 console.log('reject', error); 30 }); 31 -------output------- 32 reject four
在第一個promise對象變爲resolve後,並不會取消其餘promise對象的執行,以下例
1 /* 例3.12 */ 2 var fastPromise = new Promise(function (resolve) { 3 setTimeout(function () { 4 console.log('fastPromise'); 5 resolve('resolve fastPromise'); 6 }, 100); 7 }); 8 var slowPromise = new Promise(function (resolve) { 9 setTimeout(function () { 10 console.log('slowPromise'); 11 resolve('resolve slowPromise'); 12 }, 1000); 13 }); 14 // 第一個promise變爲resolve後程序中止 15 Promise.race([fastPromise, slowPromise]).then(function (value) { 16 console.log(value); // => resolve fastPromise 17 }); 18 -------output------- 19 fastPromise 20 resolve fastPromise 21 slowPromise //仍會執行
語法:
Promise.resolve(value); Promise.resolve(promise); Promise.resolve(thenable);
它能夠看作new Promise()
的快捷方式。
1 Promise.resolve('Success'); 2 3 /*******等同於*******/ 4 new Promise(function (resolve) { 5 resolve('Success'); 6 });
這段代碼會讓這個Promise對象當即進入resolved
狀態,並將結果success
傳遞給then
指定的onFulfilled
回調函數。因爲Promise.resolve()
也是返回Promise對象,所以能夠用.then()
處理其返回值。
/* 例3.13 */ Promise.resolve('success').then(function (value) { console.log(value); }); -------output------- Success
/* 例3.14 */ //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()
的另外一個做用就是將thenable
對象(即帶有then
方法的對象)轉換爲promise對象。
1 /* 例3.15 */ 2 var p1 = Promise.resolve({ 3 then: function (resolve, reject) { 4 resolve("this is an thenable object!"); 5 } 6 }); 7 console.log(p1 instanceof Promise); // => true 8 9 p1.then(function(value) { 10 console.log(value); // => this is an thenable object! 11 }, function(e) { 12 //not called 13 });
再看下面兩個例子,不管是在何時拋異常,只要promise狀態變成resolved
或rejected
,狀態不會再改變,這和新建promise是同樣的。
1 /* 例3.16 */ 2 //在回調函數前拋異常 3 var p1 = { 4 then: function(resolve) { 5 throw new Error("error"); 6 resolve("Resolved"); 7 } 8 }; 9 10 var p2 = Promise.resolve(p1); 11 p2.then(function(value) { 12 //not called 13 }, function(error) { 14 console.log(error); // => Error: error 15 }); 16 17 //在回調函數後拋異常 18 var p3 = { 19 then: function(resolve) { 20 resolve("Resolved"); 21 throw new Error("error"); 22 } 23 }; 24 25 var p4 = Promise.resolve(p3); 26 p4.then(function(value) { 27 console.log(value); // => Resolved 28 }, function(error) { 29 //not called 30 });
語法:Promise.reject(reason)
這個方法和上述的Promise.resolve()
相似,它也是new Promise()
的快捷方式。
1 Promise.reject(new Error('error')); 2 3 /*******等同於*******/ 4 new Promise(function (resolve, reject) { 5 reject(new Error('error')); 6 });
這段代碼會讓這個Promise對象當即進入rejected
狀態,並將錯誤對象傳遞給then
指定的onRejected
回調函數。
通過上一章的學習,相信你們已經學會使用Promise
。
總結一下建立promise的流程:
new Promise(fn)
或者它的快捷方式Promise.resolve()
、Promise.reject()
,返回一個promise對象fn
中指定異步的處理resolve
reject
若是使用ES6的箭頭函數,將會使寫法更加簡單清晰。
這一章節,將會用例子的形式,以說明promise使用過程當中的注意點及容易犯的錯誤。
情景1:reject 和 catch 的區別
onFulfilled
中發生異常的話,在onRejected
中是捕獲不到這個異常的。.then
中產生的異常能在.catch
中捕獲通常狀況,仍是建議使用第二種,由於能捕獲以前的全部異常。固然了,第二種的.catch()
也可使用.then()
表示,它們本質上是沒有區別的,.catch === .then(null, onRejected)
情景2:若是在then中拋錯,而沒有對錯誤進行處理(即catch),那麼會一直保持reject狀態,直到catch了錯誤
1 /* 例4.1 */ 2 function taskA() { 3 console.log(x); 4 console.log("Task A"); 5 } 6 function taskB() { 7 console.log("Task B"); 8 } 9 function onRejected(error) { 10 console.log("Catch Error: A or B", error); 11 } 12 function finalTask() { 13 console.log("Final Task"); 14 } 15 var promise = Promise.resolve(); 16 promise 17 .then(taskA) 18 .then(taskB) 19 .catch(onRejected) 20 .then(finalTask); 21 22 -------output------- 23 Catch Error: A or B,ReferenceError: x is not defined 24 Final Task
根據例4.1的輸出結果及流程圖,能夠看出,A拋錯時,會按照 taskA → onRejected → finalTask這個流程來處理。A拋錯後,若沒有對它進行處理,如例3.7,狀態就會維持rejected
,taskB不會執行,直到catch
了錯誤。
1 /* 例4.2 */ 2 function taskA() { 3 console.log(x); 4 console.log("Task A"); 5 } 6 function taskB() { 7 console.log("Task B"); 8 } 9 function onRejectedA(error) { 10 console.log("Catch Error: A", error); 11 } 12 function onRejectedB(error) { 13 console.log("Catch Error: B", error); 14 } 15 function finalTask() { 16 console.log("Final Task"); 17 } 18 var promise = Promise.resolve(); 19 promise 20 .then(taskA) 21 .catch(onRejectedA) 22 .then(taskB) 23 .catch(onRejectedB) 24 .then(finalTask); 25 26 -------output------- 27 Catch Error: A ReferenceError: x is not defined 28 Task B 29 Final Task
將例4.2與4.1對比,在taskA後多了對A的處理,所以,A拋錯時,會按照A會按照 taskA → onRejectedA → taskB → finalTask這個流程來處理,此時taskB是正常執行的。
情景3:每次調用then
都會返回一個新建立的promise對象,而then
內部只是返回的數據
1 /* 例4.3 */ 2 //方法1:對同一個promise對象同時調用 then 方法 3 var p1 = new Promise(function (resolve) { 4 resolve(100); 5 }); 6 p1.then(function (value) { 7 return value * 2; 8 }); 9 p1.then(function (value) { 10 return value * 2; 11 }); 12 p1.then(function (value) { 13 console.log("finally: " + value); 14 }); 15 -------output------- 16 finally: 100 17 18 //方法2:對 then 進行 promise chain 方式進行調用 19 var p2 = new Promise(function (resolve) { 20 resolve(100); 21 }); 22 p2.then(function (value) { 23 return value * 2; 24 }).then(function (value) { 25 return value * 2; 26 }).then(function (value) { 27 console.log("finally: " + value); 28 }); 29 -------output------- 30 finally: 400
第一種方法中,then
的調用幾乎是同時開始執行的,且傳給每一個then的value都是100,這種方法應當避免。方法二纔是正確的鏈式調用。
所以容易出現下面的錯誤寫法:
1 /* 例4.4 */ 2 function badAsyncCall(data) { 3 var promise = Promise.resolve(data); 4 promise.then(function(value) { 5 //do something 6 return value + 1; 7 }); 8 return promise; 9 } 10 badAsyncCall(10).then(function(value) { 11 console.log(value); //想要獲得11,實際輸出10 12 }); 13 -------output------- 14 10
正確的寫法應該是:
1 /* 改寫例4.4 */ 2 function goodAsyncCall(data) { 3 var promise = Promise.resolve(data); 4 return promise.then(function(value) { 5 //do something 6 return value + 1; 7 }); 8 } 9 goodAsyncCall(10).then(function(value) { 10 console.log(value); 11 }); 12 -------output------- 13 11
情景4:在異步回調中拋錯,不會被catch
到
1 // Errors thrown inside asynchronous functions will act like uncaught errors 2 var promise = new Promise(function(resolve, reject) { 3 setTimeout(function() { 4 throw 'Uncaught Exception!'; 5 }, 1000); 6 }); 7 8 promise.catch(function(e) { 9 console.log(e); //This is never called 10 });
情景5: promise狀態變爲resove
或reject
,就凝固了,不會再改變
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
關於promise
就先介紹到這邊了,比較基礎,有不足的地方歡迎指出,有更好的也歡迎補充~