iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0

建立一個promise

Promise是一個建構函式,與其他可以自定引數的建構函式有點不同的是,它自己帶有resolve與reject函式來傳遞promise的結果。我們在resolve()裡丟一個字串,就像當我們使用fetch()抓資料時,promise fullfilled時會回傳抓到的資料,這裡的字串就等同於那些資料,是promise fullfilled的結果;同樣的,如果再reject丟一個error message,當promise reject時,這個錯誤訊息就會被catch所承接。

const myPromise = new Promise(function (resolve, reject) {
  console.log("Async procedure start!");
  setTimeout(function () {
    if (Math.random() >= 0.5) {
      resolve("You win!");
    } else {
      reject(new Error('You lose..');
    }
  }, 2000);
});

myPromise
  .then((result) => console.log(result))
  .catch((error) => console.error(error));

callback base轉promise base

利用建立promise則可以把許多原本是callback base的寫法promise化,可以增進程式的易讀性與可維護性。
下面用兩個例子來說明怎麼把callback base轉成promise base,其中最重要的點在於:想好什麼狀況下會resove與reject,同時兩種狀態到底要回傳什麼東西。像是上面的例子:

  • resolve:當亂數產生器的結果大於或等於0.5,回傳一個字串訊息
  • reject:當亂數產生器的結果小於0.5,回傳一個錯誤訊息

fetch api

這個例子使用瀏覽器提供的web api:geolocation來擷取用戶目前的位置,getCurrentPosition這個方法可以分別引入callback function來處理成功抓到位置和報錯兩個狀態。

navigator.geolocation.getCurrentPosition(
  position => console.log(position),
  error => console.error('could not access your position')

這樣的callback base的寫法可以改成promise base。

  • resolve:當有拿到座標資料時,回傳座標
  • reject:當拿到錯誤訊息時,回傳錯誤訊息

當然,原本的寫法也是可以用,只是用一個promise包起來以後,會更方便後面串接一大堆的then, catch 和finnally,能避免calalback hell,也更好讀這樣。

const getLocation = function () {
  return new Promise(function (resolve, reject) {
    navigator.geolocation.getCurrentPosition(
      position => resolve(position),
      () => {
        reject(new Error('access failed..'));
      }
    );
  });
};
getLocation()
  .then(result => console.log(result))
  .catch(error => console.log('reject message', error));

載入圖片

圖片的載入當然是一種非同步程序,我們可以對圖片加上addEventListener,在它的callback裡寫希望載入後作哪些處理,但一樣可以改成promise base讓後面一大串的處理更好讀好維護。

  • resolve:當img element有成功載入時(故對img element設一個事件監聽,觸發事件為load),回傳img element本身
  • reject:當img element載入報錯時(故對img element設一個事件監聽,觸發事件為error),回傳錯誤訊息
const imgEl = document.createElement('img');
const imgContainer = document.querySelector('.images');

const createImage = function (path) {
  return new Promise(function (resolve, reject) {
    imgEl.src = path;
    imgEl.addEventListener('load', function () {
      imgContainer.append(imgEl);
      resolve(imgEl);
    });

    imgEl.addEventListener('error', function () {
      reject(new Error('img not found'));
    });
  });
};
createImage('./img/img-1.jpg');

今日總結

這個標題是我在開賽前定鐵人文主題時就想用的,因為那時正第一次看promise,覺得..這到底是什麼?這裡大概是我開賽前js的進度了,寫完這幾天,感覺好像自己有更敢於承諾些東西了XD

Reference

udemy-The Complete Javascript Course
鐵人賽:使用 Promise 處理非同步


上一篇
爬出callback hell的繩索:promise chaining
下一篇
這顆語法糖也太好吃了:async & await
系列文
超低腦容量學習法遇到javascript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言