ES6 — Promise基础用法详解(resolve、reject、then、catch,all,)
ES6 — Promise基礎用法詳解
Promise 是一個構造函數,它自身擁有all、reject、resolve這幾個眼熟的方法,
原型上有then、catch等同樣熟悉的方法。
所以,在開始一個Promise的時候,先new一個吧:
Promise是一個構造函數,接受一個回調函數作為參數,回調函數的參數是resolve、reject。分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。其實這里用“成功”和“失敗”來描述并不準確,按照標準來講,resolve是將Promise的狀態置為fullfiled,reject是將Promise的狀態置為rejected。不過在我們開始階段可以先這么理解,后面再細究概念。
在上面的代碼中,我們執行了一個異步操作,也就是setTimeout,1秒后,輸出“執行完成”,并且調用resolve方法。
注意!我只是new了一個對象,并沒有調用它,我們傳進去的函數就已經執行了,這是需要注意的一個細節。所以我們用Promise的時候一般是包在一個函數中,在需要的時候去運行這個函數,如:
function runAsync() {let p = new Promise((resolve, reject)=> {setTimeout(()=> {console.log('執行完成');resolve(123);}, 1000)})return p; }runAsync()這時候你應該有個疑問:包裝這么一個函數有什么作用?
在我們包裝好的函數最后,會return出Promise對象 p,也就是說,執行這個函數我們得到了一個Promise對象。Promise對象上有then、catch方法,這這個時候就可以用到它們了,看下面的代碼:
runAsync().then((result)=> {console.log(result);// 做其他操作 })在runAsync()的返回上直接調用then方法,then接收一個參數,是函數,并且會拿到我們在runAsync中調用resolve時傳的的參數。運行這段代碼,會在1秒后輸出“執行完成”,緊接著輸出 “123” 。
這個時候你可能已經明白了,原來then方法和我們平時寫的回調函數是一個道理,那我們直接寫回調函數就行了啊,為什么還要寫Promise呢?
確實在一些簡單的場景下,回調函數已經夠用,但是在現在前端的大環境和大發展的狀態下,經常會出現回調地獄的情況,你可能需要在回調函數中,再繼續回調函數,這樣下去就會很恐怖了。Promise就給我們帶來了更好的解決辦法。
Promise的優勢在于,可以在then方法中繼續寫Promise對象并返回,然后繼續調用then來進行回調操作。鏈式操作的用法
看下面一個例子,多層回調時是怎么使用的:
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; }function runAsync3() {var p = new Promise(function(resolve, reject) {setTimeout(function(){console.log('執行完成3');resolve(3);}, 1000)})return p; }runAsync1().then(function(data) {console.log(data);return runAsync2(); }).then(function(data) {console.log(data);return runAsync3(); }).then(function(data) {console.log(data);return '直接返回數據' }).then(function(data) {console.log(data); })在鏈式操作中,當一個Promise結束后,可以繼續返回一個新的Promise,在下一個then方法中繼續接收其返回的resolve。
在then方法中,你也可以直接return數據而不是Promise對象,在后面的then中就可以接收到數據了,看上面例子的最后一個。
reject的用法
說完resolve ,就不得不說reject,它們都是Promise自身的方法,簡單來說,reject方法返回的是錯誤信息,將Promise的狀態置為rejected,上面已經說過。
我們下面來看看具體的實現:
function getNumber() {var p = new Promise(function(resolve, reject) {setTimeout(function(){var num = Math.ceil(Math.random()*10);if(num<5) {resolve(num)} else {reject('數字太大了')}}, 1000)});return p; } getNumber().then(function(data) {console.log('resolve')console.log(data);},function(reason) {console.log('reject')console.log(reason); })我們創建一個隨機1-10的數,判斷大小,返回不同的resolve和reject。
首先我們可以在then方法中第二個參數來接收reject返回值。如果是大于5我們就會打印出數字太大了。
但是很多人之前都有接觸過Promise,知道還有一個catch的鏈式操作方法。它也可以用來接收reject返回的信息。來看下面的代碼:
getNumber().then(function(data) {console.log('resolve');console.log(data);}).catch(function(reason) {console.log('reject');console.log(reason); })如果數字大于5就會打印 reject 6。
如果你在then中出現了錯誤,也不會中斷程序的運行,會在catch中打印出錯誤信息:
getNumber().then(function(data) {console.log('resolve');console.log(data);console.log(somedata);}).catch(function(reason) {console.log('reject');console.log(reason); // ReferenceError: somedata is not defined})Promise.all()
簡單來說,all的作用就是并行執行多個異步操作,然后在最后一個異步程序結束后,再繼續下面的方法。
Promise // 用Promise.all來執行,all接收一個數組參數,里面的值最終都算返回Promise對象。.all([runAsync1(), runAsync2(), runAsync3()]).then(function(data) {console.log(data); // [1, 2, 3]});runAsync1(), runAsync2(), runAsync3()是我們上面中寫過的方法,不清楚的可以往上面翻一翻
根據上面的代碼我們可以看到,當三個異步程序都執行完成后,在then方法中一次返回一個data數組,是三個異步程序的返回值組成的集合。
方法很簡單,那這個方法在現實中,有哪些實用的地方呢?
打開網頁時,預先加載需要用到的各種資源如圖片、flash以及各種靜態文件。 所有的都加載完后,我們再進行頁面的初始化下面我們來看一個跟all相似,但是運行過程不同的方法race。
Promise.race()
all方法的效果實際上是「誰跑的慢,以誰為準執行回調」,
那么相對的就有另一個方法「誰跑的快,以誰為準執行回調」,這就是race方法
race 的用法:
Promise.race([runAsync1(), runAsync2(), runAsync3()]).then(function(data){console.log(data); // 1})因為第一個方法先結束,所以程序就到在此運行到then方法, 返回的 1
現實中 race 的使用也很多
可以用race給某個異步請求設置超時時間,并且在超時后執行相應的操作
/*---------- race 使用場景 ----------------*/// 請求某個圖片資源function requestImg() {var p = new Promise(function(resolve, reject) {var img = new Image();img.src = 'http://www.google.cn/landing/cnexp/google-search.png';img.onload = function() {resolve(img)}});return p;}// 延時函數,用于給請求記時function timeout() {var p = new Promise(function(resolve, reject) {setTimeout(function() {reject('請求超時')}, 5000)});return p;}Promise.race([requestImg(), timeout()]).then(function(data) {console.log(data);document.body.appendChild(data);}).catch(function(reason) {console.log(reason);})如果你把圖片的url地址替換成一個不存在的地址,那么系統會報404的錯誤,在接下來的catch中,會打印出錯誤信息請求超時
總結
以上是生活随笔為你收集整理的ES6 — Promise基础用法详解(resolve、reject、then、catch,all,)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux系统下破解 Idea的步骤
- 下一篇: sqlServer sa账号被锁定