promise學習筆記

什麼是promise?
簡單的說它是一個異步流程的控制手段。是一個表明了異步操做最終完成或者失敗的對象。
promise的優勢
promise解決了回調地獄的問題
promise能夠支持多個併發的請求
promise的錯誤傳播機制能夠統一的處理錯誤信息
回調地獄問題
在傳統的ajax調用過程當中,下面以jquery.ajax爲例。若是需求中要屢次進行ajax交互,而且上一次的返回結果還要被下一次的ajax使用,代碼基本上會變成:
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
$.ajax({php

type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function (msg) {
    $.ajax({
        type: "POST",
        url: "some.php",
        data: msg,
        success: function (msg2) {
            //... //屢次調用                 
        }
    });
}

});
如今還只是兩次調用關係,若是是屢次調用將會引起下面的問題
屢次調用不利於代碼的管理於維護
發生錯誤時不能及時準備的定位錯誤位置
只要又一次不成功就不能進行下面的邏輯,不方便進行錯誤處理。
promise的鏈式調用就很好的解決了這個問題
Promise的三種狀態
Pending Promise對象實例建立時候的初始狀態
resolve 能夠理解爲成功的狀態
Reject 能夠理解爲失敗的狀態
promise 中的狀態只能是從等待狀態轉換到成功狀態或者失敗狀態,且狀態轉變以後不可逆。jquery

一個簡單的promise
[JavaScript] 純文本查看 複製代碼
?
1
2
3
4
let p = new Promise((resolve, reject) => {ajax

console.log(1)

});
console.log(2) //1 2
promise裏面只接受一個參數,叫作執行器函數,這個函數會同步執行。也就是說上面代碼中的箭頭函數被同步執行,獲得的結果也就是1和2
promise中的then
每個promise的實例上都有一個then方法,這個方法上有兩個參數,一個是成功的回調,一個是失敗的回調。而取決於成功或者失敗的是promise的執行器函數中執行的是成功仍是失敗。
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
let p = new Promise((resolve, reject) => {數組

console.log(1);
resolve(); //調用resolve會走到then的成功回調
//reject();//調用resolve會走到then的失敗回調

});
p.then(promise

() => {
    console.log('成功')
}, () => {
    console.log('失敗')
})

//1 成功
若是既不調用resolve也不調用reject,promise則一直處於等待狀態,也就不會走到then方法。
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
let p = new Promise((resolve, reject) => {併發

console.log(1);

});
p.then(異步

() => {
    console.log('成功')
}, () => {
    console.log('失敗')
})

//1
若是你既調用resolve也調用reject,那麼誰在前面執行就走誰的對應回調函數
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
let p = new Promise((resolve, reject) => {函數

console.log(1);
resolve() //先調用成功
reject()

});
p.then(ui

() => {
    console.log('成功')
}, () => {
    console.log('失敗')
})

//1 成功
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
let p = new Promise((resolve, reject) => {url

console.log(1);
reject() //先調用失敗
resolve()

});
p.then(

() => {
    console.log('成功')
}, () => {
    console.log('失敗')
})

//1 失敗
若是代碼出錯則會直接走reject的回調
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
let p = new Promise((resolve, reject) => {

console.log(1);
throw new Error('出錯了~')

});
p.then(

() => {
    console.log('成功')
}, () => {
    console.log('失敗')
})

//1 失敗
一個promise的實例能夠then屢次
[JavaScript] 純文本查看 複製代碼
?
1
2
3
4
5
6
7
8
9
let p = new Promise((resolve, reject) => {

resolve('成功了');

});
p.then((data) => {

console.log(data) //成功了

});
p.then((data) => {

console.log(data) //成功了

})
利用promise解決回調地獄
可以規避異步操做中回調地獄的問題,其本質取決於promise的鏈式調用。假設需求以下,a.txt文件的內容爲b.txt,b.txt文件的內容是一段描述文字,如今要求用a.txt的獲得最終的描述文字,代碼以下:
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
let fs = require('fs');
//首先將異步方法封裝在一個promise中,異步結果成功調用resolve方法,失敗調用reject方法。
function read(url) {

return new Promise((resolve, reject) => {
    fs.readFile(url, 'utf8', function (err, data) {
        if (err) reject();
        resolve(data);
    })
})

}
//由於read方法返回的是一個promise,因此可使用promise的then方法
read('a.txt').then((data) => {

//第一次異步成功後拿到結果繼續返回一個promise能夠實現鏈式調用。
console.log(data); //b.txt
return read(data);

}, (err) => {}).then((data) => {

//最後兩次的結果分別對應兩次異步的返回內容
console.log(data) //描述文字

}, (err) => {})
總結:若是一個promise的then方法中還返回另外一個promise,那麼這個promise的成功狀態會走到外層promise的下一次then方法的成功,若是失敗,返回外層promise下一次then的失敗。
promise的鏈式調用
若是then中返回的是一個普通值,就會走到下一次then的成功回調。
[JavaScript] 純文本查看 複製代碼
?
1
2
3
4
5
read().then((data) => {

return 111

}, (err) => {}).then((data) => {

console.log(data) //111

}, (err) => {})

若是then中返回的是一個錯誤,就會走到下一次then的失敗回調。
[JavaScript] 純文本查看 複製代碼
?
1
2
3
4
5
6
7
read().then((data) => {

throw new Error('出錯了~')

}, (err) => {}).then((data) => {

console.log(data)

}, (err) => {

console.log(err) //出錯了~

})

若是then中什麼也不返回,就會走到下一次then的成功回調,獲得的值爲undefined。
[JavaScript] 純文本查看 複製代碼
?
1
2
3
4
5
read().then((data) => {

cons.log(111)

}, (err) => {}).then((data) => {

console.log(data) //undefined

}, (err) => {})

若是想統一處理錯誤內容,可使用catch。
[JavaScript] 純文本查看 複製代碼
?
1
2
3
4
5
read().then((data) => {
throw new Error('出錯了~')
}, (err) => { }).then((data) => {}, (err) => {}).catch((err)=>{

//錯誤處理

})

統一處理錯誤後,還可使用then。
[JavaScript] 純文本查看 複製代碼
?
1
2
3
4
5
read().then((data) => {
throw new Error('出錯了~')
}, (err) => { }).then((data) => {}, (err) => {}).catch((err)=>{

//錯誤處理

}).then((data) => {}, (err) => {})

Promise.all()
all方法能夠處理多個請求併發的問題。參數是一個數組。all方法調用後會返回一個新的promise。
[JavaScript] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
let fs = require('fs');

function read(url) {

return new Promise((resolve, reject) => {
    fs.readFile(url, 'utf8', function (err, data) {
        if (err) reject();
        resolve(data);
    })
})

}
Promise.all([read('1.txt'), read('2.txt')]).then((data) => {

console.log(data) //[ '文本1內容', '文本2內容' ]

}, (err) => {

console.log(err);

})
在all方法中一個失敗了就所有失敗,因此都成功了纔會走成功回調。
[JavaScript] 純文本查看 複製代碼
?

Promise.all([read('1.txt'), read('3.txt')]).then((data) => {

console.log(data)

}, (err) => {

console.log('失敗了'); //失敗了

})
Promise.race()
多個請求中,誰的返回數據最快,結果就是誰
[JavaScript] 純文本查看 複製代碼
?
1
Promise.race([read('1.txt'), read('2.txt')]).then((data) => {/indent console.log(data)////文本2內容/indent}, (err) => {/indent console.log('失敗了');//失敗了/indent})
Promise.resolve()
返回一個成功的Promise
[JavaScript] 純文本查看 複製代碼
?

Promise.resolve('123').then((data) => {

console.log(data) //123

})
Promise.reject()
返回一個失敗的Promise
[JavaScript] 純文本查看 複製代碼
?

Promise.resolve('123').then((data) => {

console.log('err', data) //err 123

})更多技術資訊可關注:gzitcast

相關文章
相關標籤/搜索