Promise和Async/Await

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 概念三明治

Similar Posts