所謂Promise,簡(jiǎn)單來說就是一個(gè)容器,里面保存著某個(gè)未來才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語法上來說,Promise是一個(gè)對(duì)象,從它可以獲取異步操作的消息。Promise提供統(tǒng)一API,各種異步操作都可以用同樣的方法進(jìn)行處理。
ES6規(guī)定,Promise 是一個(gè)構(gòu)造函數(shù),用來生成promise實(shí)例
var promise = new Promise(function(resolve, reject){
// ... some code
if (/* 異步操作成功 */) {
resolve(value)
} else {
reject(error)
}
})
Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是resolve和reject,它們是兩個(gè)函數(shù),由js引擎提供,不需要自己部署
resolve的作用是,將Promise對(duì)象的狀態(tài)從‘未完成’變成‘成功’,也就是異步操作成功時(shí)調(diào)用,并將操作的結(jié)果作為參數(shù)傳遞出去,reject函數(shù)與resolve相反,將Promise對(duì)象的狀態(tài)從‘未完成’變成‘失敗’,就是在異步操作失敗時(shí)時(shí)調(diào)用,并將錯(cuò)誤作為參數(shù)傳遞出去
Promise實(shí)例生成以后,可以用then方法分別指定Resolved狀態(tài)和Rejected狀態(tài)的回調(diào)函數(shù)
promise.then(function(value){
// success do something
}, function(error){
// failure do something
})
then方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù),第一個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)镽esolved時(shí)調(diào)用,第二個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)镽ejected時(shí)調(diào)用。其中,第二個(gè)函數(shù)是可選的,不一定要提供,但是異常捕獲是考驗(yàn)我們代碼健壯性必不可少的,最好是有。這兩個(gè)函數(shù)都接受Promise對(duì)象傳出的值作為參數(shù)
下面是一個(gè)Promise對(duì)象的簡(jiǎn)單例子:
function timeout (ms) { // timeout 函數(shù)返回Promise實(shí)例
return new Promise(function(resolve, reject) {
setTimeout(resolve, ms, 'done') // Promise未來要發(fā)生的事情,這里直接將‘done’字符串作為成功的結(jié)果通過resolve函數(shù)返回出去
})
}
timeout(100).then(function(value) { // then函數(shù)第一個(gè)參數(shù)是Promise對(duì)象的狀態(tài)成功時(shí)調(diào)用,在控制臺(tái)會(huì)將value打印出來,也就是我們?cè)谏厦娼oresolve函數(shù)傳遞的‘done’字符串
console.log(value)
})
Promise新建后就會(huì)立即執(zhí)行,它會(huì)確定實(shí)例是Resolved或者Rejected狀態(tài),進(jìn)而觸發(fā)對(duì)應(yīng)的回調(diào)
let promise = new Promise(function(resolve, reject){ // 立即執(zhí)行,并且打印‘Promise’
console.log('Promise')
resolve()
})
promise.then(function(){ // 異步操作要等同步操作執(zhí)行完成之后執(zhí)行,所以最后打印‘Resolved’
console.log('Resolved')
})
console.log('Hi!') // js由上而下執(zhí)行同步操作,其次打印‘Hi’
/*
依次打印
Promise
Hi
Resolved
*/
Promise對(duì)象有以下兩個(gè)特點(diǎn)。
1、對(duì)象的狀態(tài)不受外界影響。Promise對(duì)象代表一個(gè)異步操作,有3種狀態(tài): Pending(進(jìn)行中), Fulfilled(已成功) 和 Rejected(已失敗)。只有異步操作的結(jié)果可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個(gè)狀態(tài)。這也是Promise這個(gè)名字的由來,它在英語種的意思就是承諾,表示其他手段無法改變。
2、一旦狀態(tài)改變就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果。Promise對(duì)象的狀態(tài)改變只有兩種可能:從Pedding變成Fulfilled和從Pedding變成Rejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會(huì)再變,而是一直保持這個(gè)結(jié)果,這時(shí)就稱為Resolved(已定型)。就算改變已經(jīng)發(fā)生,再對(duì)Promise對(duì)象添加回調(diào)函數(shù),也會(huì)立即得到這個(gè)結(jié)果。
我們來看一個(gè)簡(jiǎn)單的例子:
function loadImg(src) {
var promise = new Promise(function(resolve, reject) {
var img = document.createElement('img')
img.onload = function () {
resolve(img)
}
img.onerror = function () {
reject()
}
img.src = src
})
return promise
}
var src = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
var result = loadImg(src)
result.then(function(img) {
console.log(1, img.width)
return img
}, function() {
console.log('error 1')
}).then(function(img) {
console.log(2, img.height)
})
大部分瀏覽器目前都支持Promise標(biāo)準(zhǔn),部分老版本IE不支持,可以在BootCDN找bluebird鏈接,在js中引入
<script src="https://cdn.bootcss.com/bluebird/3.5.3/bluebird.min.js"></script>