iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 5
0
自我挑戰組

React 30 天學習歷程系列 第 5

【Day 5】React 中常用的一些 ES6 語法 (三)

這一篇主要提到的都是關於非同步以及同步處理的方式,ES6 有提供 Promise 來處理同步非同步行為,後續也有 async await 讓非同步行為更容易處理。

Promise

Promise 其實是一個原生的構造函數,可以透過 new 來生成實例。它接受一個函式作為參數,這個參數會有 resolve 和 reject 兩個參數,分別代表成功和失敗。Promise 中總共有三種狀態,pending(等待、未完成)、resolve(成功)、reject(失敗)。
Promise 的使用一般是先用 new 生成一個實例,賦給變數,之後藉由呼叫該變數直接調用,如下面的範例。我們可以在實例中去判斷 resolve 和 reject 時要執行什麼事情。調用 Promise 後可以用 then 來接續去取得 Promise 執行後回傳的結果。thenPromise 實例的一個方法,接受兩個回調函數作為參數(reject, resolve),執行完後會返回一個 promise 物件,因此可以用 then 再接下去,一直 then, then...。catch 是非同步異常時候會執行的事情,finally 則是無論成功失敗,都會執行的事情。

const promise = new Promise((resolve, reject) => {
    if (true) {
        resolve(1);//resolve 會返回一個值,這個返回的數值實際上掛在 promise 實例裡面
    } else {
        reject(2);
    }
})

promise.then( //訪問 then,then 會返回一個新的 promise
    //resolve 回調函數
    value => {
        console.log(value)//1,resolve 回調函數
        // 成功要執行的事情
        return 10
    },
    error => {
        // 失敗要執行的事情
        console.log(error)//2,reject 回調函數
        return 5
    }
).then(
    value => {
        console.log(value)//10
        return 20
    },
    error => {
        console.log(error)
        return 5
    }
).then(
    value => {
        console.log(value)//20
        return 30
    },
    error => {
        console.log(error)
        return 5
    }
).catch (error => {
    //非同步異常
}).finally(() => {
    //沒有參數
    //無論失敗成功都會執行
});

Promise.all 與 Promise.race

這邊整理兩個一次執行多個 Promise 的方法,Promise.allPromise.race
Promise.all() 會同時執行所有 Promise,並在全部完成後統一回傳陣列,這個陣列的內容也是 Promise 中 resolve 的內容,但如果當中有 reject 事件,整個 Promise 都會被視為失敗。
Promise.race 可以傳入多個 Promise 事件,這個方法只會回傳第一個完成的事件。

const bikeRace = (name, time) => {
    return new Promise((resolve, reject) => {
        if(time > 0) {
            setTimeout(() => {
                let str = name + '花費' + (time / 1000) +'秒完成比賽';
                resolve(str);
            }, time)
        } else {
            let str = name + '於比賽中作弊~!!!!';
            reject(str);
        };
    });
};

Promise.race([bikeRace('Leo', 12000), bikeRace('Jack', 9000), bikeRace('Lun', 13000), bikeRace('Willie', 30000)]).then((data) => {
    // 只會回傳最快完成的 reslove 或 reject
    console.log(data) // "Jack 花費 9 秒完成跑完 100 公尺"
}).catch((error) => {
    console.log(error)
});

Promise.all([bikeRace('Leo', 12000), bikeRace('Jack', 9000), bikeRace('Lun', 13000), bikeRace('Willie', 30000)]).then((data) => {
    // 回傳全部結果
    console.log(data) //["Leo 花費 12 秒完成跑完 100 公尺", "Jack 花費 9 秒完成跑完 100 公尺", "Lun 花費 13 秒完成跑完 100 公尺", "Willie 花費 30 秒完成跑完 100 公尺"]
}).catch((error) => {
    console.log(error)
});

Promise.all([bikeRace('Leo', 12000), bikeRace('Jack', 9000), bikeRace('Lun', 13000), bikeRace('Willie', 0)]).then((data) => {
    // 回傳全部結果
    console.log(data) //Willie跑步時閃到腰摔倒~!!!!
}).catch((error) => {
    console.log(error)
});

async await 非同步處理

ES8 引入了 asyncawait 函數讓非同步處理更為方便,asyncawait 是建構於 Promise 之上的。Promise 中完成會透過 then 來回傳,在 await 則是會等待這段函式完成後再往下繼續執行。由於 await 如果遇到錯誤就會造成停止讓後方程式碼不執行,因此通常搭配 async 使用。async 的結構非常類似 Promise,只不過他能夠將 await 包在裡面,被包在裡面的 await 就如同先前的結構一樣,會依序地執行。async 本身也是類似 Promise,在正確執行的情況下 return 會傳回 resolved 的狀態,也可以使用 then 來接收正確的資料,並使用 catchfinally 來執行非同步失敗及最後要執行的事情

基本用法

await 接非同步處理行為,通常是接 Promise,並且會等到處理完畢回傳,才會繼續執行的程式碼。如下面的範例,await 後面接著 fetch 去發出 request,之後會返回一個 PromisePromise 會透過 then 做處理返回我們需要的資料,直到這些事情都執行完畢,才會執行後續的程式碼。如果沒有用 then 之類的方法,得到的會是 response,並不是真的數據,必須再使用如 .json() 之類的方法做處理。

async function getApi() {
    try {
        const res = await fetch('./post.json').then(res => res.json());
    
    } catch(err) {
        //異步異常
        console.log(err)
    } finally {
        console.log('done')
    }
};

//調用
getApi();

async 函數是返回一個 Promise 物件,async 如果有返回值,返回值會成為 then 方法回調的函數

async function getApi() {
    try {
        return await fetch('./post.json');
    
    } catch(err) {
        //異步異常
        console.log(err)
    } finally {
        console.log('done')
    }
};

getApi().then(res => {
    return res.json(); //async 返回的 promise 物件會在第一個 then 裡面調用
})

匿名自執行 async

定義一個匿名自己執行的 async 函式

(async () => {
    const res = await fetch('./post.json').then(res => res.json());
})();

async 多種寫法

//函數聲明
async function test() {

};

//函數表達式
const test = async function() {

};

//物件寫法
let obj = {
    name: 'leo',
    async test () {
    
    }
};

obj.test();

//class 寫法
class TestComponent {
    async test () {
    
    }
};

const a = new Test();
a.test();

//箭頭函式
const test = async () => {

};

小結

這一篇主要是整理 ES6 中處理非同步的方式,下一篇開始會整理 JSX 的使用方式。


上一篇
【Day 4】React 中常用的一些 ES6 語法 (二)
下一篇
【Day 6】用 JSX 來寫 HTML 標籤
系列文
React 30 天學習歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言