摘要:上代碼異步執行成功的構造函數接收一個函數參數,并傳入兩個參數,分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。第一個回調函數是對象的狀態變為時調用,第二個回調函數是對象的狀態變為時調用。
這篇文章只解決三個問題。
什么是promise?
promise有什么用?
promise怎么用?
1.什么是promise?
對于ES6來說,就是一個構造函數,可以用new Promise( )來創建Promise實例。
2.promise有什么用?
先想象兩個場景:
一,業務中,需要請求后臺的兩個接口,但是需要第一個返回成功結果之后再請求第二個接口,這是可能會寫成下面這個樣子,
var request = function(){ var xhr1 = new XMLHttpRequest(); xhr1.onreadystatechange = function(){ if(xhr1.readyState !== 4){ alert("第一步請求失敗了,請重試!"); return; } if(xhr1.status === 200){ console.log("第一步請求成功了,我們開始下一步吧!"); var xhr2 = new XMLHttpRequest(); xhr2.open("GET", url); xhr2.onreadystatechange = function(){ if(xhr2.readyState !== 4){ alert("第二步請求失敗了,請重試!"); return; } if(xhr2.status === 200){ //兩次請求成功后做的一些事情.... } else { alert("第二步請求失敗了,請重試!"); } }; xhr2.responseType = "json"; xhr2.setRequestHeader("Accept", "application/json2"); xhr2.send(); } else { alert("第一步請求失敗了,請重試!"); } }; xhr1.responseType = "json"; xhr1.setRequestHeader("Accept", "application/json1"); xhr1.send(); }); } request();
上面代碼用xhr對象實現了兩次異步請求,代碼很長。不過這僅僅是兩層回調嵌套,想象一下更多的異步回調依賴有多可怕…
二,我們都知道,nodejs的一大特點就是事件驅動,那就肯定要利用事件的回調函數來處理邏輯,多層的回調嵌套也就在所難免。那么你的代碼很可能就會寫成這個德行,
async(1,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,function(value){ async(value,final); }); }); }); }); }); }); }); })
就此你掉進了又長又丑的嵌套地獄。
咋辦?
用promise(回答了“promise是干啥的”)。
咋用?
往下看。
3.promise 怎么用?
在學習怎么使用Promise的同時,需要不時接觸幾個關于它的知識點。能理解最好,理解不了用著用著就理解了。
首先需要了解的是每個Promise實例都有三種狀態:
1.進行中狀態 pending
2.成功狀態 resolved
3.失敗狀態 rejected
同一時間下Promise實例只能有一種狀態,且只能改變一次,改完之后就再也不能變了。
變化的途徑只有兩種,第一,從pending變為resolved;第二,從pending變為rejected。
接下來就一步步的完成一個promise的使用。
第一步,new一個Promise實例。上代碼:
var promise = new Promise(function(resolve,reject){ if(/*異步執行成功*/){ resolve(value) } else { reject(error) } });
Promise的構造函數接收一個函數參數,并傳入兩個參數resolve,reject分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。執行resolve(),會將當前promise對象的狀態更改為resolved,執行reject()會將當前promise對象的狀態更改為rejected。
這時一個Promise對象已經創建完成,異步腳本的結果也已經被存在這個Promise對象中了,但它是成功是失敗?我們怎么讀取呢?
第二步,then方法。接著上代碼:
var promise = new Promise(function(resolve,reject){ if(/*異步執行成功*/){ resolve(value); } else { reject(error); } }); promise.then(function(value){ console.log(value); },function(error){ console.log(error); })
每個Promise實例都有一個then方法,它就是處理Promise中存儲的異步執行結果的方法。then方法可以接受兩個回調函數作為參數。第一個回調函數是Promise對象的狀態變為Resolved時調用,第二個回調函數是Promise對象的狀態變為Reject時調用。其中,第二個函數是可選的,不一定要提供。這兩個函數都接受Promise對象傳出的值作為參數。
需要特別注意的是then方法的返回值還是一個Promise!這就意味著then方法是支持鏈式調用的。
第三步,catch方法。
catch方法等同于then(null,function(){}),也就是用來處理rejected狀態下Promise數據的。關于catch個人認為記住兩點就好。第一,用catch來處理rejected的Promise;第二,用catch來捕獲之前所有鏈式調用中拋出的Error對象,注意是所有,包括Promise構造函數、then方法、鏈式調用的then方法、以及之前的catch,這些步驟拋出的錯誤都可以被catch捕獲。
var promise = new Promise(function(resolve,reject){ if(false){ resolve(value); } else { reject(error); } }); promise .then(function(value){ console.log(value); }) .catch(function(reason){ console.log(error); })
上面代碼會輸出reject(error)傳入的error值,也就是catch的第一種用法。
var promise = new Promise(function(resolve,reject){ if(true){ resolve(value); } else { reject(error); } }); promise .then(function(value){ console.log(value); console.log(x); }) .catch(function(reason){ console.log(reason); })
上面代碼會將Promise的狀態改為resolved,并執行then方法,在then方法中會拋出一個x變量未定義的錯誤,并由catch方法捕獲到并打印出來,這就是catch的第二個用法。
至此實際上我們已經學會了Promise的基礎應用。接下來再學習兩個比較好用的方法。
第一個,Promise.all方法。
該方法能夠并行運行異步方法,并在結果都返回之后進行統一處理,并返回一個新的Promise對象。
var p = Promise.all([p1, p2, p3]);
上面代碼中,Promise.all方法接受一個“數組”作為參數,p1、p2、p3都是Promise對象的實例。
p的狀態由p1、p2、p3決定,分成兩種情況。
(1)只有p1、p2、p3的狀態都變成fulfilled,p的狀態才會變成fulfilled,此時p1、p2、p3的返回值組成一個數組,傳遞給p的回調函數。(fulfilled可以理解為resolved)
(2)只要p1、p2、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。
var p = Promise.all([p1,p2,p3]); p.then(function(results){ console.log(results) });
當打開網頁時,需要預先加載各種資源如圖片、flash以及各種靜態文件,所有的都加載完后,我們再進行頁面的初始化。這種場景是很適合使用Promise.all的。
第二個,Promise.race方法。
與all方法類似,同樣是能夠并行運行異步方法,并在結果都返回之后進行統一處理,并返回一個新的Promise對象。
var p = Promise.race([p1,p2,p3]);
上面代碼中,只要p1、p2、p3之中有一個實例率先改變狀態,p的狀態就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數,也就是說誰執行的快就返回誰的。
race方法可以添加請求超時的限制。
//請求某個圖片資源 function requestImg(){ var p = new Promise(function(resolve, reject){ var img = new Image(); img.onload = function(){ resolve(img); } img.src = "xxxxxx"; }); return p; } //延時函數,用于給請求計時 function timeout(){ var p = new Promise(function(resolve, reject){ setTimeout(function(){ reject("圖片請求超時"); }, 5000); }); return p; } Promise .race([requestImg(), timeout()]) .then(function(results){ console.log(results); }) .catch(function(reason){ console.log(reason); });
到這,關于Promise的三個問題已經解答完了,希望能夠為大家學習Promise提供一點幫助。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82256.html
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網絡基礎知識之 HTTP 協議 詳細介紹 HTT...
摘要:意味著操作成功完成。當調用方法的時候會設置一個狀態,調用方法的時候會設置一個狀態。返回是自定義的,狀態由自己設但不能不給狀態,不然不會執行下一個鏈詳細文檔文檔 背景:在一個方法中處理一個復雜的異步操作時會涉及到多個異步處理,它們可能是層層嵌套導致這個方法異常的龐大,影響日后的代碼維護和問題的查找 解決:在ES6中提供了一個Promise的對象,它以一種鏈式的寫法將異步操作邏輯與異步返...
摘要:首先是一個構造器函數,使用它必須通過一個實例出來,并且出來的實例暈有一個內置的參數,這個參數是一個函數,這個參數擁有自己內置的兩個參數,和,并且這兩個參數也是兩個函數異步操作成功上面這個就是一個最簡單的對象屬于的一個方法,里面的兩個參數屬于 首先promise是一個構造器函數,使用它必須通過new一個實例出來,并且new出來的實例暈有一個內置的參數,這個參數是一個函數,這個參數擁有自己...
摘要:首先是一個構造器函數,使用它必須通過一個實例出來,并且出來的實例暈有一個內置的參數,這個參數是一個函數,這個參數擁有自己內置的兩個參數,和,并且這兩個參數也是兩個函數異步操作成功上面這個就是一個最簡單的對象屬于的一個方法,里面的兩個參數屬于 首先promise是一個構造器函數,使用它必須通過new一個實例出來,并且new出來的實例暈有一個內置的參數,這個參數是一個函數,這個參數擁有自己...
摘要:源碼學習本篇為上一篇源碼學習的補充,主要是來介紹和方法。那個率先改變的實例的返回值,就傳遞給的回調函數。基本介紹可見阮一峰老師的書籍。的狀態由決定,分成兩種情況。只有的狀態都變成,的狀態才會變成,此時的返回值組成一個數組,傳遞給的回調函數。 Promise源碼學習(2) 本篇為上一篇源碼學習(1)的補充,主要是來介紹Promise.all()和Promise.race()方法。閑話少敘...
閱讀 1692·2021-11-23 09:51
閱讀 3209·2021-09-26 10:21
閱讀 807·2021-09-09 09:32
閱讀 889·2019-08-29 16:06
閱讀 3318·2019-08-26 13:36
閱讀 781·2019-08-26 10:56
閱讀 2573·2019-08-26 10:44
閱讀 1153·2019-08-23 14:04