Promise的理解與使用
Promise的理解
Promise是什么
抽象的表達就是:Promise 是異步編程的一種解決方案,
而具體點的表達就是:
- 在語法上:Promise 是一個建構式;
- 在功能上:Promise 物件是用來封裝一個異步操作并可以從中獲取結果;
Promise的狀態
Promise 只有三種狀態,分別為初始狀態(pending)、成功狀態(fulfilled / resolved)、失敗狀態(rejected),
- pending(初始狀態): 初始狀態,既不是成功,也不是失敗狀態;
- fulfilled / resolved(已成功): 意味著操作成功完成;
- rejected(已失敗): 意味著操作失敗;
而在這三種狀態之間,Promise 物件的狀態改變只有兩種情況,分別是:
- 從初始狀態(pending)變為成功狀態(fulfilled / resolved);
- 從初始狀態(pending)變為失敗狀態(rejected);
只要上面這兩種情況發生了,狀態就凝固了,不會再變了,會一直保持這個結果,
一個 Promise 物件只能改變一次狀態,無論最后是變成成功還是失敗,都會有一個資料結果,
為什么要用Promise
使用 Promise 的原因有如下兩點:
- 指定回呼函式的方式更加靈活
- 支持鏈式呼叫,可以解決回呼地獄的問題
那么回呼地獄又是什么呢?
回呼地獄即回呼函式嵌套呼叫,外部回呼函式異步執行的結果是嵌套的回呼的執行條件,
而回呼地獄十分不便于開發者閱讀,也不利于進行例外處理,因此,使用 Promise 的鏈式呼叫可以解決此類問題,
Promise的基本使用
Promise 的基本書寫語法大致如下:
function fn() {
return new Promise((resolve, reject) => {
成功時呼叫 resolve(value)
失敗時呼叫 reject(error)
})
}
fn().then(成功函式1, 失敗函式1).then(成功函式2, 失敗函式2)
let p = new Promise((resolve, reject) => {
setTimeout(() => {
let time = Date.now()
console.log(time)
if (time % 2 === 1) {
resolve(time)
} else {
reject(time)
}
}, 1000)
})
p.then((value) => {
console.log('成功的回呼' + value)
}, (error) => {
console.log('失敗的回呼' + error)
})
Promise的API
Promise.prototype.then
Promise 實體具有then方法,也就是說,then方法是定義在原型物件Promise.prototype上的,該方法回傳一個新的 promise 物件,
它的作用是為 Promise 實體添加狀態改變時的回呼函式,then方法的第一個引數是resolved狀態的回呼函式,第二個引數(可選)是rejected狀態的回呼函式,
let p1 = new Promise((resolve, reject) => {
...
})
p1.then(value =https://www.cnblogs.com/LqZww/p/> {...}, error => {...})
Promise.prototype.catch
Promise.prototype.catch() 方法是 .then(null, rejected) 或 .then(undefined, rejected) 的別名,用于指定發生錯誤時的回呼函式,
let p1 = new Promise((resolve, reject) => {
reject('error')
})
p1.then(value =https://www.cnblogs.com/LqZww/p/> {
console.log(value)
}).catch(error => {
console.log(error)
})
Promise.resolve
Promise.resolve() 回傳一個成功 Promise 物件,
// value: 成功的資料或 Promise 物件
Promise.resolve(value)
let p1 = Promise.resolve('p1')
// 等價于
let p1 = new Promise(resolve => {
resolve('p1')
})
Promise.reject
Promise.reject() 回傳一個失敗的 Promise 物件,
// error: 失敗的原因
Promise.reject(error)
let p2 = Promise.reject('error')
// 等價于
let p2 = new Promise((resolve, reject) => {
reject('error')
})
Promise.all
Promise.all() 方法用于將多個 Promise 實體包裝成一個新的 Promise 實體,傳入的引數為陣列形式,
該 Promise 物件在陣列引數物件里所有的 Promise 物件都成功的時候才會觸發成功,一旦有任何一個陣列引數物件里面的 Promise 物件失敗則立即觸發該 Promise 物件的失敗,
// promise1 、promise2 、 promise3 都成功才會呼叫成功函式,否則呼叫失敗函式
Promise.all([promise1, promise2, promise3, ...]).then(成功函式, 失敗函式)
let p1 = new Promise((resolve, reject) => {
resolve('p1')
})
let p2 = new Promise((resolve, reject) => {
resolve('p2')
})
let p3 = new Promise((resolve, reject) => {
reject('p3')
})
let pAll1 = Promise.all([p1, p2, p3]).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log(value)
}, error => {
console.log(error) // p3
})
let pAll2 = Promise.all([p1, p2]).then(value => {
console.log(value) // (2) ["p1", "p2"]
}, error => {
console.log(error)
})
Promise.all() 回傳一個新的 Promise, 只有所有的 Promise 都成功才成功, 只要有一個失敗了就直接失敗,
Promise.race
Promise.race() 方法同樣是將多個 Promise 實體,包裝成一個新的 Promise 實體,傳入的引數為陣列形式,
race 翻譯過來大致就是“比賽”的意思,因此,第一個完成的 Promise 的結果狀態就是最終的結果狀態,
// 如果 promise1 為成功狀態并先完成,那么最終將執行成功函式;如果 promise1 為失敗狀態并先完成,那么最終將執行失敗函式,
Promise.race([promise1, promise2, promise3, ...]).then(成功函式, 失敗函式)
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p2')
}, 2000)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('p3')
}, 3000)
})
Promise.race([p1, p2, p3]).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log(value) // p1
}, error => {
console.log(error)
})
手寫Promise - 待完善
相關問題與題目
如何改變Promise的狀態
Promise 狀態的改變除了上面所說的從 pendding 變為 resolved 和 pendding 變為 rejected 之外,還有一種可以改變狀態,那就是拋出例外,會從 pendding 就會變為 rejected,
let p = new Promise((resolve, reject) => {
throw new Error('error')
})
p.then(
value =https://www.cnblogs.com/LqZww/p/> {},
error => {
console.log(error) // Error: error
}
)
改變Promise狀態和指定回呼函式的誰先誰后
都有可能,一般情況下先指定回呼函式然后再改變的狀態,但是也可也先改變狀態然后再指定回呼函式
如下兩種方法可以先改變狀態然后再指定回呼函式:
- 在執行器中直接呼叫 resolve() / reject()
- 添加 setTimeout 延遲更長的時間呼叫 .then()
// 先指定的回呼函式,并保存當前指定的回呼函式,然后改變的狀態,再執行異步回呼函式
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 1000)
})
p1.then(value =https://www.cnblogs.com/LqZww/p/> {
console.log(value)
}, error => {
console.log(error)
})
// 先改變的狀態,然后指定回呼函式,并異步執行回呼函式
let p2 = new Promise((resolve, reject) => {
resolve('p2')
})
p2.then(value =https://www.cnblogs.com/LqZww/p/> {
console.log(value)
}, error => {
console.log(error)
})
// 先改變的狀態,然后指定回呼函式,并異步執行回呼函式
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p3')
}, 1000)
})
setTimeout(() => {
p3.then(value =https://www.cnblogs.com/LqZww/p/> {
console.log(value)
}, error => {
console.log(error)
})
}, 1200)
.then()回傳的新Promise的結果狀態由什么決定
- 如果回傳的是非 Promise 的任意值, 新 Promise 變為 resolved, value 為回傳的值;
- 如果回傳的是另一個新 Promise, 那么這個 Promise 的結果就會成為新 Promise 的結果 ;
- 如果拋出例外, 新 Promise 變為 rejected, error 為拋出的例外;
new Promise((resolve, reject) => {
resolve('hh')
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo1,' + value) // demo1,hh
}, error => {
console.log('demo1,' + error)
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo2,' + value) // demo2,undefined
}, error => {
console.log('demo2,' + error)
})
new Promise((resolve, reject) => {
resolve('hh')
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo1,' + value) // demo1,hh
return 1
}, error => {
console.log('demo1,' + error)
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo2,' + value) // demo2,1
}, error => {
console.log('demo2,' + error)
})
new Promise((resolve, reject) => {
resolve('hh')
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo1,' + value) // demo1,hh
return Promise.resolve('3')
}, error => {
console.log('demo1,' + error)
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo2,' + value) // demo2,3
}, error => {
console.log('demo2,' + error)
})
new Promise((resolve, reject) => {
resolve('hh')
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo1,' + value) // demo1,hh
return Promise.reject('4')
}, error => {
console.log('demo1,' + error)
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo2,' + value)
}, error => {
console.log('demo2,' + error) // demo2,4
})
new Promise((resolve, reject) => {
resolve('hh')
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo1,' + value) // demo1,hh
throw 5
}, error => {
console.log('demo1,' + error)
}).then(value =https://www.cnblogs.com/LqZww/p/> {
console.log('demo2,' + value)
}, error => {
console.log('demo2,' + error) // demo2,5
})
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/70536.html
標籤:JavaScript
上一篇:JavaScript連載16-回呼函式、作用域鏈條、預決議
下一篇:html5之table嵌入form表單布局(務必注意:table標簽必須在form表單內部,不能再form表單外部!)
