Promise是什麼?
Promise是一個ES6新語法,
MDN的解釋是 Promise 物件代表一個即將完成、或失敗的非同步操作,以及它所產生的值
用白話一點解釋是:它承諾幫你做某事,做完會通知你結果(成功or失敗)
使用方法
用new Promise建立一個 Promise 物件,
它帶有兩個參數resolve, reject,分對應成功與失敗,
function myPromise(){
return new Promise((resolve, reject)=>{
})
}
成功後可以用.then()抓取結果,失敗則用.catch()
function myPromise(){
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
if(true){
resolve('Success');
}else{
reject('Fail');
}
}, 0)
})
}
myPromise()
.then(res => {
console.log(res)
})
.catch(res => {
console.log(res)
})
結果:Success
Promise Chain
如果我們有多個非同步行為,無法得知每個完成的時間,
但又要讓它們依照順序執行,此時就可以用多個then來串接。
function testA() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success A')
resolve('Success A')
//這裡用Math.random()模擬獲取伺服器api的不定時間
}, Math.random() * 1000)
})
}
function testB() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success B')
resolve('Success B')
}, Math.random() * 1000)
})
}
function testC() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success C')
resolve('Success C')
}, Math.random() * 1000)
})
}
testA()
.then(testB)
.then(testC)
Promise.all和Promise.race
假設我今天是要三個非同步行為都成功後,才做下一件事,
這個時候就可以用Promise.all,它接收一組由Promise物件組成的陣列,當全都回傳resolve,它才會做下一件事,反之只要有一個reject,就會失敗。
Promise.race則是只要一個成功就會做下一件事。
function testA() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success A')
resolve('Success A')
}, Math.random() * 1000)
})
}
function testB() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success B')
resolve('Success B')
}, Math.random() * 1000)
})
}
function testC() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success C')
resolve('Success C')
}, Math.random() * 1000)
})
}
Promise.all([
testA(),
testB(),
testC()
])
.then(res => {
console.log(res[0],res[1],res[2])
})
.catch(res => {
console.log('失敗')
})
Async/Await
雖然說一般的Promise寫法就已經很好了,但如果要處理多個非同步事件,用好幾個.then串連還是有點不直觀,所以在JavaScript ES7版本 就出現了Async/Await,它的底層也是Promise,所以其實就是Promise的語法糖,只是寫法更直觀 更易讀易懂。
語法糖:對功能沒有影響,但讓撰寫方式更簡單的語法
用法是將Async,放在function前,宣告這個函式是一個Async函式,並且它會回傳一個Promise
Await,一定要寫在Async函式內,並搭配另一個Promise使用,它的作用是讓我們的程式依序執行,它會等待所搭配的Promise執行完成後,才會繼續往下
function testA() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success A')
resolve('Success A')
}, Math.random() * 1000)
})
}
function testB() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success B')
resolve('Success B')
}, Math.random() * 1000)
})
}
function testC() {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log('Success C')
resolve('Success C')
}, Math.random() * 1000)
})
}
async function myAsync() {
await testA();
await testB();
await testC();
}
myAsync();
當遇到await,async function就會知道要先暫停,等await搭配的Promise執行完後,再繼續往下執行
結合Promise.all使用
async function fetch1() {
return 'fetch1'
}
async function fetch2() {
return 'fetch1'
}
async function getApi() {
const all = await Promise.all([fetch1(),fetch2()])
}
記得嗎,async會回傳一個Promise,這裡的fetch1和fetch2函式就是利用這點創造Promise。再搭配Promise.all來完成想要的邏輯
Reference:
JavaScript概念三明治