关于ES6的Promise
JavaScript的異步處理
提到JavaScript的異步處理,也許很多人和我一樣想到利用回調函數。
例如:
firstAsync(function(data){//處理得到的 data 數據//....secondAsync(function(data2){//處理得到的 data2 數據//....thirdAsync(function(data3){//處理得到的 data3 數據//....});}); });但是回調函數一旦嵌套層級過多,就會引發“回調地獄”的問題,而Promise作為一種異步解決方案,就可以很好的解決這個問題。
例如上面的例子用Promise實現的話:
firstAsync() .then(function(data){//處理得到的 data 數據//....return secondAsync(); }) .then(function(data2){//處理得到的 data2 數據//....return thirdAsync(); }) .then(function(data3){//處理得到的 data3 數據//.... });什么是 Promise?
Promise是一個對象,用于表示一個異步操作的最終狀態(完成或失敗),以及其返回的值。它作為ES6最重要的特性之一,目前已經被Firefox和Chrome等主流瀏覽器所支持,具體情況可以在Can I use里查看。如果想要做瀏覽器的兼容,只需要在瀏覽器中加載Polyfill類庫即可。
Promise 的狀態
- 等待(pending):初始狀態。
- 已完成(fulfilled):意味著操作成功完成。
- 已失敗(rejected):意味著操作失敗。
Promise對象的狀態只可能處于這三種之一,它的狀態改變只可能是兩種可能:從 Pending 變為 fulfilled 和從 Pending 變為 Rejected。一旦狀態發生改變,就不會再變,這也是Promise[承諾]這個名字的由來。
then 鏈式操作和 resolve 方法
Promise.prototype.then 方法返回的是一個新的 Promise 對象,因此可以采用鏈式寫法。該方法接收兩個參數,第一個是成功的回調,第二個是失敗的回調。
下面用setTimeout模擬異步操作:
function runAsync1(){var p = new Promise(function(resolve, reject){setTimeout(function(){console.log('異步操作1執行完畢!');resolve('異步操作1成功回調數據');}, 1000);});return p; } function runAsync2(){var p = new Promise(function(resolve, reject){setTimeout(function(){console.log('異步操作2執行完畢!');resolve('異步操作2成功回調數據');}, 1000);});return p; }使用 Promise.prototype.then 方法鏈式調用這兩個方法:
runAsync1() .then(function(data){console.log(data);return runAsync2(); }) .then(function(data){console.log(data); });運行結果如下:
你也可以在 then 方法中直接return數據而不是Promise對象:
runAsync1() .then(function(data){console.log(data);return runAsync2(); }) .then(function(data){console.log(data);return '直接返回數據' }) .then(function(data){console.log(data) });運行結果如下:
reject 方法
上面我們通過 Promise.resolve() 把Promise的狀態置為已完成(Resolved), 然后通過 then 方法捕捉到變化,并執行“成功”情況的回調,而 Promise.reject() 的作用就是將Promise的狀態置為已失敗(rejected),同樣通過 then 方法來執行“失敗”情況的回調。
function runAsync1(num){var p = new Promise(function(resolve, reject){ setTimeout(function(){console.log('異步操作1執行完畢!');if(num < 10) {resolve('異步操作1成功回調數據');}else{reject('異步操作1失敗回調數據'); }}, 1000);});return p; }運行結果如下:
catch 方法
Promise.prototype.catch 和 Promise.prototype.then 方法的第二個參數一樣,用來指定reject的回調,二者都返回 promise 對象, 因此都可以被鏈式調用。
此外 catch 還可以捕獲異常:
all 方法
Promise.all(iterable) 返回一個新的promise對象,該promise對象只有在iterable參數對象里所有的promise對象都成功的時候才會觸發成功,并所有promise返回值以數組的形式返回。
以上面的 runAsync1() 和 runAsync1() 為例:
Promise .all([runAsync1(),runAsync2()]) .then(function(results){console.log(results); });返回結果如下:
race 方法
Promise.race() 方法,race即競賽,顧名思義,這是一個比誰跑得快的規則。
function runAsync1(){var p = new Promise(function(resolve, reject){setTimeout(function(){console.log('異步操作1執行完畢!');resolve('異步操作1成功回調數據');}, 2000);});return p; } function runAsync2(){var p = new Promise(function(resolve, reject){setTimeout(function(){console.log('異步操作2執行完畢!');resolve('異步操作2成功回調數據');}, 1000);});return p; } Promise .race([runAsync1(),runAsync2()]) .then(function(results){console.log(results); });運行結果如下:
可以看到,只要runAsync1、runAsync2中的任何一個率先改變狀態,父Promise的狀態就跟著改變。而那個率先改變狀態的子Promise的返回值,就是傳遞給父Promise的返回值。
總結
Promise的基本使用方法就是這樣,之前看過一篇文章,用做飯(cook)吃飯(eat)洗碗(wash)為例,形象地演示了Promise的用法,地址戳戳戳這里。
- 參考文檔
更多專業前端知識,請上 【猿2048】www.mk2048.com
總結
以上是生活随笔為你收集整理的关于ES6的Promise的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消除switch语句以获得更好的代码结构
- 下一篇: Socket.io 深入理解