iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 8
4
Modern Web

30天走訪Progressive Web Apps(PWAs)系列 第 8

Day8-Fetch API與Promise 使用方式介紹

在練習fetch之前,讓我們先談談promise,再PWAs裡面,很常會看到promise的蹤影,像在一開始註冊的時候,就會回傳promise型別,如果成功就會執行then,因此,就來複習一下用法吧!

navigator.serviceWorker.register('/service-worker.js')
        .then(function(){
            console.log('Service Worker 註冊成功');
        });

Javascript的執行方式

前面說過Js是一條執行序,因此我們預期當我們有A、B和C三個任務,執行時,應該是依序A、B和C執行,但實際上Javascript上是以非同步的方式執行,畫了一張示意圖如下。
https://ithelp.ithome.com.tw/upload/images/20171223/20103808IsAOtUHE8I.jpg
箭頭上方的是我們原本預期會依序執行的方式,但實際上,javascript會以非同步的方式先載入,再等程式執行完後回傳。

 setTimeout(function(){
        resolve('三秒過後執行');
    },3000);
console.log('再Timeout之後執行');

以一個簡單的測試方式,原先預期的結果應該是

三秒過後執行
再Timeout之後執行

實際是

再Timeout之後執行
三秒過後執行

這個測試跟Promise什麼關係呢?

我們將上面的測試以Promise的方式實作

var promise = new Promise(function(resolve,reject){
    setTimeout(function(){
        resolve('三秒過後執行');
    },3000);
});
promise.then(function(result){
    console.log(result);
});
console.log('再Timeout之後執行');

新增Promise時,會發現function中傳了resolverejectresolve代表當成是執行成功時會回傳的東西,而reject代表在過程中發生錯誤時,會回傳的物件。
Promise本身回傳的結果也是以非同步的方式進行,但是它有趣的一點是能將很多非同步的事情,串成一條龍,讓你能有順序的方式執行。

為了驗證一下,所以將字串「再Timeout之後執行」的程式碼接再then後面。

promise.then(function(result){
    console.log(result);
    return result;
}).then(function(result){
    if(result != undefined && result != '')
    console.log('再Timeout之後執行');
});

https://ithelp.ithome.com.tw/upload/images/20171224/20103808oUSPLWReRJ.jpg
如上面的執行結果,3秒後,Promise將字串回傳了第一個then,印出後接著回傳結過到下一個then,才印出「再Timeout之後執行」。

而如果要抓錯誤訊息了話,試著將resolve改成reject

reject({code: 500,message: '發生錯誤'});

then後面接catch,就可以接到錯誤訊息了。

promise.then(function(result){
    console.log(result);
    return result;
}).then(function(result){
    if(result != undefined && result != '')
    console.log('再Timeout之後執行');
}).catch(function(err){
    console.log(err.code+' '+err.message); 
});

https://ithelp.ithome.com.tw/upload/images/20171224/20103808C2aRQXogFK.jpg
以上就是Promise最基本的用法,接著就回到fetch的話題吧~

Fetch API

為了體驗fetch的效果,可以到http://httpbin.org/
有許多可以讓我們測試getpost的資料,以下就來測試

GET

抓取現在的ip位置做測試,

fetch('http://httpbin.org/ip')
    .then(function(response){
        console.log(response);
        return response.json();
    })
    .then(function(data){
        console.log(data);      
    })
    .catch(function(err){
        console.log(err);
    });

給了fetch要抓取ip的網址,當成功抓到的時候我們就回傳response
https://ithelp.ithome.com.tw/upload/images/20171224/201038088baNhsTRsi.jpg
從訊息上來看,成功回傳了ip位置,而且status:200表示資料抓取正常。

那麼接著故意來把網址打錯看一下catch的結果
https://ithelp.ithome.com.tw/upload/images/20171224/20103808QVc4NdNQ1g.jpg
由於fetch找不到「 http://httpbin.org/ipa 」這個網址,因此就噴了catch,回傳status:404,找不到網頁的錯誤訊息。

Post

fetch('http://httpbin.org/post',{
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    },
    mode: 'cors',
    body: JSON.stringify({message: 'POST資料是否成功'})
    })
    .then(function(response){
        console.log(response);
        return response.json();
    })
    .then(function(data){
        console.log(data);      
    })
    .catch(function(err){
        console.log(err);
    });

接著來用fetch實作一下POST的方法,使用「 http://httpbin.org/post 」,並在後面可以傳一個請求的物件內容,接著讓我們POST一個json資料格式過去,再看看then,能不能接收到post成功的訊息。

https://ithelp.ithome.com.tw/upload/images/20171224/201038083lmoxMhjWb.jpg
console視窗如願,看到了我們設定的json訊息,這樣就成功透過fetch做簡易的POST請求。

Polyfill 當舊的瀏覽器不支援Promise或Fetch API

GitHub上有幾個認可的PromiseFetch API可以使用,當瀏覽器吃不到功能時,可以藉由這些實作特色的library來代替。

Promise在官網有提到四種替代函式庫

Fetch

以Promise做示範

if(!window.Promise){
    window.Promise = Promise;
}

當瀏覽器找不到Promise的時候,就將函式庫的功能指定給瀏覽器的Promise
這樣就能讓某些較舊的瀏覽器也能吃到API的好處了。

總結

PromiseFetch還有許多細節的學問,但是我想就此打住,避免學習主題的失焦,也怕內容越打越長/images/emoticon/emoticon56.gif,因此,今天就先稍微了解API的基本的使用方式,接下去在讓我們將這個特色發揮到Service Worker上吧!


上一篇
Day7-Service Worker 走訪Lifecyle(程式篇)
下一篇
Day9-Service Worker中的Fetch事件
系列文
30天走訪Progressive Web Apps(PWAs)30

1 則留言

0
Ho.Chun
iT邦新手 5 級 ‧ 2019-12-11 18:25:15

請問下,這樣說是否正確呢 ?
Service Worker本身也是條執行續,所以依舊有Event Loop那些觀念在 !
/images/emoticon/emoticon16.gif

我要留言

立即登入留言