iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0
Modern Web

了不起的 Svelte系列 第 20

第 20 天:Svelte 中的邏輯運作:`await` 邏輯區塊

  • 分享至 

  • xImage
  •  

第 20 天:Svelte 中的邏輯運作:await 邏輯區塊

「然而她卻不明白。」說道這,他頓了一頓:「她以前是能夠明白的。我們會送出請求,然後在那兒 await 幾個小時…」

~節錄自《The Great Svelte:第六章》

第 20 天要講的事

  1. 介紹 Svelte 的 await 邏輯區塊語法
  2. 在專案中使用 await 邏輯區塊

  今天我們要介紹第三種 Svelte 所提供的邏輯段落:await 邏輯段落。在設計前端專案的時候,或多或少會需要用到 Javascript 的非同步語法 Promise 來取得資料,並將資料呈現在 HTML 的元素當中。舉例來說,我們可能會想要使用 fetch 去其他伺服器端抓取需要的資料,將抓取回來的資料做一些運算處理之後,將結果呈現在 HTML 的元素當中。既然這個動作是結合了 Javascript 的邏輯運算去驅動 HTML 元素的變化,Svelte 當然也很貼心的提供了相對應的邏輯段落幫我們方便的實現這個功能。

介紹 Svelte 的 await 邏輯區塊語法

  在 Javascript 當中,Promise 有三種狀態:等待 (pending)、實現 (fulfilled)、拒絕 (rejected)。Svelte 提供的 await 邏輯區塊讓我們可以輕鬆地針對這三種狀態來呈現不同的 HTML 元素。

{#await promise}
  <!-- 等待階段所呈現的 HTML 元素 -->
{:then result}
  <!-- 實現階段所呈現的 HTML 元素 -->
{:catch error}
  <!-- 拒絕階段所呈現的 HTML 元素 -->
{/await}
  • 第一行:{#await promise}
      用 {#await} 展開 await 邏輯段落。該邏輯段落的 HTML 呈現方式由 promise 這個 Promise 的狀態來決定。

  • 第二行:<!-- 等待階段所呈現的 HTML 元素 -->
      當 promise 還在等待階段 (pending) 時,呈現這個段落的 HTML 元素。

  • 第三行:{:then result}
      用 {:then} 展延 await 邏輯段落。這是一個表示 promise 到達實現階段 (fulfilled) 的邏輯段落,並將 promise 實現所得到的結果放進變數 result

  • 第四行:<!-- 實現階段所呈現的 HTML 元素 -->
      當 promise 到達實現階段 (fulfilled) 時,呈現這個段落的 HTML 元素。

  • 第五行:{:catch error}
      用 {:catch} 展延 await 邏輯段落。這是一個表示 promise 到達拒絕階段 (rejected) 的邏輯段落,並將 promise 發生錯誤導致拒絕的內容放進變數 error

  • 第六行:<!-- 拒絕階段所呈現的 HTML 元素 -->
      當 promise 到達拒絕階段 (rejected) 時,呈現這個段落的 HTML 元素。

  • 第七行:{/await}
      最後用 {/await} 關閉這個邏輯段落。

  順順的看下來,一切的設計是不是都很直覺呢。這是最完整的 await 邏輯段落,分別應對三種 Promise 狀態來搭配不同的 HTML 元素。不過有些時候我們並不在意等待階段 (pending),或是我們信心十足,根本不怕 Promise 被拒絕 (rejected)。Svelte 當然也提供這樣的彈性,讓我們可以針對實際需求來簡化 await 邏輯段落。
舉例來說,如果我們在等待階段並不特別想要呈現任何 HTML 元素:

{#await promise then result}
  <!-- 實現階段所呈現的 HTML 元素 -->
{:catch error}
  <!-- 拒絕階段所呈現的 HTML 元素 -->
{/await}

  或是我們並不想要特別處理拒絕階段的 HTML 元素:

{#await promise}
  <!-- 等待階段所呈現的 HTML 元素 -->
{:then result}
  <!-- 實現階段所呈現的 HTML 元素 -->
{:catch error}
{/await}

  或是我們並不想要特別處理實現階段的 HTML 元素 (咦?):

{#await promise}
  <!-- 等待階段所呈現的 HTML 元素 -->
{:catch error}
  <!-- 拒絕階段所呈現的 HTML 元素 -->
{/await}

  這些種種變化都是可以的喔!

在專案中使用 await 邏輯區塊

  好的,介紹完了 await 邏輯區塊的語法以及各種花式變形,就讓我們用自己的專案實際來試一試吧。為了做出 Promise,今天我們找來了一個有趣的 API:Color API。這是他的官方網站。Color API 提供快速查找顏色相關資訊,如 Hex 碼、RGB 碼,甚至還有顏色名稱。這邊以 Svelte 的代表橘色來實際的玩一玩。
  在網址列輸入https://www.thecolorapi.com/id?hex=ff3e00&format=html 應該會看到如圖一的結果:

https://ithelp.ithome.com.tw/upload/images/20231005/201201789aWLhKKBxD.png
圖一、詳細解說了 Svelte 代表橘色

  或是在網址列輸入 https://www.thecolorapi.com/id?hex=ff3e00,應該就會拿到一個 JSON 的資料。仔細研究一下這個資料,可以看到我們諮詢的顏色 ff3e00,其詳細的色碼,如 hexrgbhsl 等等,還有該顏色的名稱 name。我們今天就來替色票產生器裡頭的不同色票多補上相對應的顏色名稱吧。

/src/lib/Palettes.svelte
<script>
  import { createEventDispatcher } from "svelte";
  import unlock from "../assets/unlock.svg";
  import lock from "../assets/lock.svg";
  export let palettes;

  const dispatch = createEventDispatcher();
  const handleClick = (id) => dispatch("changeLock", id);

  const getHexName = async (hex) => {
    const url = `https://www.thecolorapi.com/id?hex=${hex}`;
    const res = await fetch(url);
    const json = await res.json();
    return json.name.value;
  };
</script>

<div class="palettes">
  {#each palettes as { hex, id, locked } (id)}
    <div class="card">
      <div class="palette" style="background: #{hex}" />
      <div class="hex-code">
        <p>
          {hex}
        </p>
        <p>
          {#await getHexName(hex)}
            wait...
          {:then name}
            {name}
          {/await}
        </p>
      </div>
      <!-- svelte-ignore a11y-no-static-element-interactions a11y-click-events-have-key-events -->
      <div class="lock-icon" on:click={() => handleClick(id)}>
        {#if locked}
          <img src={lock} alt="color-locked" />
        {:else}
          <img src={unlock} alt="color-unlocked" />
        {/if}
      </div>
    </div>
  {:else}
    <div class="card no-color">
      <div>
        <p>No color to show. Please add a color.</p>
      </div>
    </div>
  {/each}
</div>
  • 第十行:const getHexName = async (hex) => {
      宣告一個函式 getHexName,這個函式需要一個參數,也就是我們色票的 Hex 色碼。

  • 第十一行:const url = https://www.thecolorapi.com/id?hex=${hex};
      先把我們需要的 API 網址做好。

  • 第十二行:const res = await fetch(url);
      用 fetch 向 API 提出請求,抓取需要的資料。

  • 第十三行:const json = await res.json();
      得到回覆後,再用 json() 取得 JSON資料。

  • 第十四行:return json.name.value;
      因為我們只需要顏色名稱,所以用 json.name.value 把顏色名稱拿出來,並作為函數的回傳值。

  • 第二十七行:{#await getHexName(hex)}
      用 {#await} 開啟 await 的邏輯區塊。而 Promise 自然是 getHexName(hex)

  • 第二十八行:wait...
      如果 Promise getHexName(hex) 仍然在等待階段,那就顯示 wait…

  • 第二十九行:{:then name}
      用 {:then} 展延 await 邏輯區塊,並將 Promise 到達實現階段得到的結果以變數 name 表示。

  • 第三十行:{name}
      如果 Promise 來到實現階段,成功傳回結果,那就將 name,也就是顏色名稱顯示出來。

  • 第三十一行:{/await}
      由於我們不擔心(或是說不想處理) fecth 失敗,所以直接用 {/await} 結束 await 邏輯區塊。

  這就是今天所有的程式碼了。讓我們看看 Color API 為我們的色票準備了哪些顏色名稱吧。

https://i.ibb.co/zf4zKnN/20.gif
圖二、Vermilion、Robins Egg Blue、Cerulean…

  那麼今天關於 await 邏輯區塊的介紹就到這邊了,詳細的程式碼可以在 Github 資源庫找到。謝謝大家。


上一篇
第 19 天:Svelte 中的邏輯運作:`if` 邏輯區塊
下一篇
第 21 天:Svelte 的生命週期函式:`onMount`
系列文
了不起的 Svelte30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言