1 - 非同步之認識Promise


Posted by backas36 on 2021-07-21

先來複習使用 XMLHttpRequest 的正常情況

For練習用的 產生各種 api 網站,Mocky

const api200 = 'https://run.mocky.io/v3/98c6ea3a-2359-429d-8be1-98396934af0f'
// 完全正常運作的 server

const api500 = 'https://run.mocky.io/v3/bf2b926c-0db4-4f98-b09a-1211d4da6038'
// 假裝 server error 回傳 500 的 api

const apiJsonError = 'https://run.mocky.io/v3/3bf6bbd8-6b7c-47f7-8b92-9efb2a0a8dfc'
// 回傳 200 但是 json 格式錯誤的 api

const apiWrongUrl = 'https://srun.mocky.io/v3/98c6ea3a-2359-429d-8be1-98396934af0f'
// 一個錯的 url 

// 測試是否非同步
console.log(1)

const request = new XMLHttpRequest();
request.open('GET', api200, true);
// 第三個參數 true,就算未指定預設也是 true 是取得資料的方式為 asynchronously,若為 false 則會設定為同步。

request.onload = function () {
  if (this.status >= 200 && this.status < 400) {
    let data
    try {
      data = JSON.parse(this.response)

    } catch (error) {
      console.log(error)
      return
      // apiJsonError 的結果
    }
    console.log(data) // api200的結果

  } else {
    console.log('Here hava error (ex: 404, 500)from server, but we got repsonese is successful')
    // api500 的結果
    return
  }
};

request.onerror = function () {
  console.log('Here have error by request url or others reason')
  //apiWrongUrl的結果
}

request.send();

console.log(2)
console.log(3)
//先印出 123 才回傳 api 資料! 非同步,成功!

範例中有設定不同錯的 api url,可以使用該變數去假裝錯誤,好去了解是哪邊產生了錯誤。(Mocky 的 api 連結有效期,過期可以告訴我一聲)

因為目前自己對網路也沒有很熟悉,就現在的能力只能預設會產生的錯誤有 1)回傳的json有錯 (apiJsonError)、 2)當 server 有內部錯誤的時候回傳HTTP status Code 500 (api500)、 3)當自身的url有錯,或者 client 端網路連線有 error 你可以拔掉網路線試試看 (apiWrongUrl)。
或者可以直接使用 api200 一切正常的情況下去跑跑看這段程式。

以上是使用 XMLHttpRequest 的方式串 api,並且看見了console.log(1),console.log(2),console.log(3)會先印出來,才會回傳 api 的資料。

先介紹一下 Promise

Promise 會自動生成 resolvereject function,並且只會回傳其中一個,不是 resolve, 就是 reject。

以下的範例,因為尚未串 API 為範例,只是利用變數 data 來假裝一下是 API 回傳的資料,把data放入 resolve function,接著我們執行 myPromise() 會回傳 error Uncaught TypeError: myPromise is not a function,因為 myPromise 是 Promise 並不是 function ,所以我不能使用 myPromise() 這種方式拿到 data。

我們必須使用 then() 來接收 data,就會拿到這個 "This is fake API data" 😬 。

重點要記住,只要是 Promise ,就是要用 then(),來接收 data 。

const data = 'This is fake API data'

const myPromise = new Promise((resolve, reject) => {
  resolve(data)
})

//myPromise() 這樣是錯的
myPromise
  .then(data => {
    console.log(data)
  })

接著我們來證明是不是非同步的。

如果執行以下程式碼會看到先回傳 1,2,3 才是 "This is fake API data"

const data = 'This is fake API data'

//測試是否同步
console.log(1)

const myPromise = new Promise((resolve, reject) => {
  resolve(data)
})

//myPromise() //這樣是錯的
myPromise
  .then(data => {
    console.log(data)
  })

console.log(2)
console.log(3)

但是串 API 很有可能會回傳錯誤,例如我們剛剛 XMLHttpRequest 範例提到的那些錯誤類型,就是要靠 reject 來回傳,並且我們接收 reject 回傳的 error 並不適用 then,而是我們要在使用 Promise 的時候在 then 後面接上 catch

const data = 'This is fake API data'


const myPromise = new Promise((resolve, reject) => {
  //resolve(data) 
  reject('OMG ERROR') //回傳 OMG ERROR
})

//myPromise() //這樣是錯的
myPromise
  .then(data => {
    console.log(data)
  })
  .catch(error => {
    console.log(error) // OMG ERROR
  })

初步認識了 Promise 之後,下一篇將會展示如何利用 Promise 串 API,再來介紹 fetch, async 與 await 吧。

第一次寫文章不宜太長,分篇寫好了 😆
1 - 非同步之認識Promise
2 - 非同步之Promise串 API
3 - 非同步之認識 fetch
4 - 非同步之認識 async/await


#非同步 #javascript #Promise







Related Posts

使用 Matter.js 2D 物理引擎製作動畫

使用 Matter.js 2D 物理引擎製作動畫

漫談傳輸介面-I2C

漫談傳輸介面-I2C

[第十六週] 從收納初探 object oriented

[第十六週] 從收納初探 object oriented


Comments