Fetch 與 Promise (一):初探 Fetch


Posted by s103071049 on 2021-07-10

若要在前端網站發 AJAX Request,有兩種方法

法一、XML HTTP Request,簡稱 xhr
法二、Fetch

要串 api 練習,但沒有 api 怎麼辦 ?
透過mocky,可以自己創造出一個 response,然後就可以自己抓 response 回來。

Fetch 怎麼用 GET

fetch(網址) === 發 request

  <script>
    fetch('https://run.mocky.io/v3/82ec874a-086c-48ef-8195-37686b61f372')
  </script>

接著想看,call 這個 funct 會回傳甚麼東西

  <script>
    const result = fetch('https://run.mocky.io/v3/82ec874a-086c-48ef-8195-37686b61f372')
    console.log(result)
  </script>

回傳後出現了 promise。promise 是一個物件的類型,比如說使用 jQuery 時,$(.button) 這個 function 回傳的會是一個 jQuery 的物件,Promise 也是一個獨特的物件,就跟正規表達是 RegExp 也是一個獨特的物件一樣。fetch 會回傳 Promise 這個獨特的物件,但其他的 functon 也可能會回傳 Promise

要拿到 Promise 的結果,要使用 .then(),括號內要接的是一個 callback function。

  <script>
    function printResult(a) {
      console.log(a)
    }
    const result = fetch('https://run.mocky.io/v3/82ec874a-086c-48ef-8195-37686b61f372')
    result.then(printResult)
  </script>

a 會是一個 response,我們成功拿到回傳的結果。

可以簡化上述 code

    fetch('https://run.mocky.io/v3/82ec874a-086c-48ef-8195-37686b61f372')
      .then((a) => {
        console.log(a)
      })

取 response 的 status

  <script>
    const api500 = 'https://run.mocky.io/v3/c5989253-8bcf-4f6a-970a-c393cdd5090e'
    const api200 = 'https://run.mocky.io/v3/82ec874a-086c-48ef-8195-37686b61f372'
    function printResult(a) {
      console.log(a)
    }
    fetch(api500)
      .then((response) => {
        console.log(response.status)
      })
  </script>

絕大多數時候,我們想要的是 response 的內容,直接 console.log(response.body) 會出現 => ReadableStream,會不知道怎麼讀他。所以 response 上面提供了幾個方法

法一、response.text() => 回傳的會是 promise

    const api500 = 'https://run.mocky.io/v3/c5989253-8bcf-4f6a-970a-c393cdd5090e'
    const api200 = 'https://run.mocky.io/v3/82ec874a-086c-48ef-8195-37686b61f372'
    function printResult(a) {
      console.log(a)
    }
    fetch(api500)
      .then((response) => {
        response.text().then(text => {
          console.log(text)
        })
      })

法二、response.json() => 回傳的會是 promise
與法一的不同在於,會將 response 的內容用 json.parse 變成一個 json 的字串。
他相當於是法一做了這件事

    .then((response) => {
        response.text().then(text => {
          console.log(JSON.parse(text))
        })
      })

fetch() 回傳的會是 promise
response.text()、response.json() 回傳的也會是 promise
response.json().then() 回傳的還是 promise
promise 要拿資料必須透過 .then() 括號接 cb function 就可以拿到資料

.then() 無窮無盡 Chaining

.then 裡面又 .then 很難閱讀,所以可以利用 promise 的神奇特性
.then return 的東西會是下一個 .then 裡面的值。如果 return 是 undefined,.then 裡面的值就是 undefined。

    fetch(api200)
    .then((response) => {
        console.log(response.status)
        response.text().then(text => {
          console.log((text))
          return 123
        }).then((abc) => {
          console.log('abc', abc) //abc 123
        })
      })

不 return 任何東西,預設就是 undefined,所以 abc 就是 undefined

    fetch(api200)
    .then((response) => {
        console.log(response.status)
        response.text().then(text => {
          console.log((text))
        }).then((abc) => {
          console.log('abc', abc) //abc undefined
        })
      })

為甚麼 .then() 完還可以再 .then() ?
因為 .then() 也是一個 function,所以 .then() 這個 function 回傳的還是一個 promise,所以可以再繼續接續下去。

這跟這個很像,當我們呼叫 css 這個 function,這個 function 的回傳值是另外一個 jQuery 的物件,所以她又可以再 .hide(),.hide() 回傳的也是一個 jQuery 的物件,所以可以再 .show(),因為一直 return 自己,才可以做到這樣的事情,我們叫他 chaining。

$('.button').css(...).hide().show()

return 的東西如果是 promise,那我再下一個 .then 拿到的值,就會是解析完的值

這個 text 是 response.text() 這個 promise 的回傳值。

response.text().then(text =>)

我拿到的 abc 就會是 response.text() 的結果

    fetch(api200)
      .then((response) => {
        return response.text()
      }).then(abc => {
        console.log(abc)
      })

可以利用這個特性,縮排較少,更好閱讀拿到資料。cb 大時代極力避免很多層、縮排很多,因為會很難追蹤程式碼。

重點回顧

  1. return 的是值,他會自動帶到下面去
  2. return 的是 promise,會將 promise 解析完後,用 .then 的方式拿出來的值,帶到下面去。(可以利用這樣的方式,拿到 json 格式的資料)

#Fetch 與 Promise







Related Posts

系列文背景與簡介

系列文背景與簡介

AppWorks School Batch #16 Front-End Class 學習筆記&心得(駐點階段四:個人專案~Sprint 5)

AppWorks School Batch #16 Front-End Class 學習筆記&心得(駐點階段四:個人專案~Sprint 5)

Django aggregate and annotate

Django aggregate and annotate


Comments