iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
Modern Web

Web Bluetooth API 實戰:30 天打造通用 BLE 偵錯工具系列 第 5

DAY5:程式的邏輯:運算子、流程控制和迴圈

  • 分享至 

  • xImage
  •  

大家好!在內容中,我們已經成功為我們的程式準備了原材料——學會了如何使用變數來儲存資料,並了解了資料型態這個收納盒的規格。我們現在擁有了程式世界的「名詞」,像是數字、字串和布林值。

然而,光有材料還不足以實現建造我們藍圖。今天,我們要為建築的藍圖用的「大腦」和「神經系統」。我們要學習程式的「動詞」與「思考模式」——運算子流程控制

想像一下,當我們的工具掃描到一個藍牙裝置時,它該如何做出判斷?「這個裝置的訊號強度大於-70dBm 嗎?」、「這個特徵是可以讀取還是只能訂閱?」這些決策,就是程式邏輯的體現。

今天,我們將學習如何使用 if...else 這個強大的工具,賦予程式判斷是非、做出選擇的能力。這不僅是學習語法,更是掌握如何將我們的開發意圖,轉化為機器能夠理解並執行的指令。學完今天,你就能搭建起整個專案最核心的邏輯骨架:動態地根據藍牙裝置的特性,生成獨一無二的操作介面

  1. 運算子 (Operators)

    • 比較運算子:用來比較兩個值,並回傳一個布林值 (truefalse)。這在 if 判斷中非常重要。

      • >:大於

      • <:小於

      • ===:嚴格等於(值和型別都相等)

      • !==:不等於

    • 邏輯運算子:用來組合多個條件,最終也回傳 truefalse

      • && (AND): 兩個條件都為 true,結果才為 true

      • || (OR): 只要有一個條件為 true,結果就為 true

      • ! (NOT): 將 truefalsefalsetrue

  2. 流程控制 (Flow Control):if...else 流程控制就像是程式的「交通號誌」,它決定了程式碼要走哪一條路。if...else 是最基本也最重要的流程控制語法。

    • 基本結構
      if (條件為 true) {
        // 執行這裡的程式碼
      } else {
        // 如果條件為 false,就執行這裡的程式碼
      }
      

這是一個簡單的例子,判斷一個數字是否大於10。

let score = 20;

if (score > 10) {
  console.log("分數高於10分!"); // 這行會被執行
} else {
  console.log("分數等於或低於10分。");
}

在我們的 BLE 工具中,每個藍牙「特徵 (Characteristic)」都有一組「屬性 (Properties)」,定義了我們可以對它做什麼操作(讀、寫、訂閱等)。我們需要用
if...else 來檢查這些屬性,然後動態地在網頁上生成對應的按鈕。例如:如果這個特徵的屬性包含 read,我們生成一個「讀取」按鈕;否則,就不生成 。

讓我們來模擬一下第13天的核心功能 。假設我們從藍牙裝置拿到一個特徵物件

characteristic,它的 properties 屬性會告訴我們它能做什麼 。

/**
 * 模擬一個從藍牙裝置讀取到的特徵 (Characteristic) 物件
 * `properties` 物件裡的布林值,表示該特徵是否具備某項能力
 */
const characteristic = {
  uuid: '00002a37-0000-1000-8000-00805f9b34fb', // 心率特徵的 UUID
  properties: {
    read: false,        // 這個特徵不可讀
    write: false,       // 這個特徵不可寫
    notify: true        // 這個特徵可以被訂閱 (Notify)
  }
};

/**
 * 根據特徵屬性,決定要顯示什麼 UI 描述
 */
function generateUIdescription(char) {
  console.log(`正在分析特徵 (UUID: ${char.uuid}) 的功能...`);

  // 檢查是否可以讀取 (read)
  if (char.properties.read === true) {
    console.log("-> 應生成「讀取 (Read)」按鈕");
  }

  // 檢查是否可以寫入 (write)
  if (char.properties.write === true) {
    console.log("-> 應生成「寫入 (Write)」輸入框與按鈕");
  }
  
  // 檢查是否可以訂閱 (notify)
  if (char.properties.notify === true) {
    console.log("-> 應生成「訂閱 (Notify)」開關");
  }

  // 如果什麼功能都沒有
  if (char.properties.read === false && char.properties.write === false && char.properties.notify === false) {
    console.log("-> 此特徵為靜態,無互動功能");
  }
}

// 執行函式,傳入我們模擬的特徵物件
generateUIdescription(characteristic);

// 預期輸出:
// 正在分析特徵 (UUID: 00002a37-0000-1000-8000-00805f9b34fb) 的功能...
// -> 應生成「訂閱 (Notify)」開關

這個範例完美展示了我們如何使用 if 語句來判斷 properties 物件中的布林值,並根據結果印出不同的訊息。在後續的實作中,我們只需將 console.log 換成實際創建 HTML 元素的程式碼即可。

3. 重複的力量:迴圈 (Loops)

學會了判斷,接下來我們要學習如何處理重複性的任務。在我們的專案中,一個藍牙裝置可能不只有一個「服務 (Service)」,一個服務底下也可能不只有一個「特徵 (Characteristic)」。我們總不能一個一個手動處理吧?這時,迴圈就派上用場了。迴圈能讓我們重複執行同一段程式碼,直到滿足特定條件為止。

  • for 迴圈:當你知道需要重複執行的「次數」時,for 迴圈是你的好朋友。特別是在處理陣列 (Array) 這種集合資料時。在我們的專案中,for...of 迴圈將會是我們的核心武器,它能優雅地遍歷陣列中的每一個元素 。

    for...of 結構

    for (const item of array) {
      // 對每個 item 執行這裡的程式碼
    }
    

    讓我們模擬一下遍歷藍牙裝置回傳的服務列表:

    // 模擬從藍牙裝置掃描到的服務列表 (這是一個陣列)
    const services = [
      { uuid: '0000180d-0000-1000-8000-00805f9b34fb', name: '心率服務' },
      { uuid: '0000180f-0000-1000-8000-00805f9b34fb', name: '電池服務' },
      { uuid: '0000180a-0000-1000-8000-00805f9b34fb', name: '裝置資訊服務' }
    ];
    
    console.log("開始遍歷所有藍牙服務...");
    
    // 使用 for...of 迴圈,依序取出 services 陣列中的每一個 service 物件
    for (const service of services) {
      // 在迴圈內,我們可以對每一個 service 進行操作
      console.log(`發現服務: ${service.name} (UUID: ${service.uuid})`);
      // 在未來的實作中,我們會在這邊接著去呼叫 getCharacteristics() 來取得該服務下的所有特徵
    }
    
    console.log("所有服務遍歷完畢!");
    
    // 預期輸出:
    // 開始遍歷所有藍牙服務...
    // 發現服務: 心率服務 (UUID: 0000180d-0000-1000-8000-00805f9b34fb)
    // 發現服務: 電池服務 (UUID: 0000180f-0000-1000-8000-00805f9b34fb)
    // 發現服務: 裝置資訊服務 (UUID: 0000180a-0000-1000-8000-00805f9b34fb)
    // 所有服務遍歷完畢!
    

    這就是我們在第23天「動態探索所有特徵」時會用到的核心語法 。

  • while 迴圈:當你不知道要重複幾次,只知道「當某個條件成立時,就繼續做」的情況下,while 迴圈就非常有用。

    while 結構

    while (條件為 true) {
      // 執行這裡的程式碼
      // (記得要更新條件,否則會變成無窮迴圈!)
    }
    

    例如,我們可以模擬一個等待使用者點擊按鈕的場景:

    let isConnected = false;
    let connectionAttempts = 0;
    
    while (isConnected === false && connectionAttempts < 5) {
      console.log(`第 ${connectionAttempts + 1} 次嘗試連線...`);
      connectionAttempts++; // 每次嘗試後,計數器加 1
    
      // 模擬在第 3 次嘗試時成功連線
      if (connectionAttempts === 3) {
        isConnected = true;
        console.log("連線成功!");
      }
    }
    
    if(isConnected) {
        console.log("藍牙裝置已準備就緒。");
    } else {
        console.log("連線失敗,已達嘗試上限。");
    }
    

總結

今天我們學會了程式的「判斷力」(if...else) 與「耐力」(for, while)。這兩者結合起來,就能創造出複雜且智慧的邏輯。我們現在不僅能讓程式根據不同情況走不同的路,還能讓它不知疲倦地處理大量重複的工作。

掌握了這些,我們就離打造出那個能自動分析並生成介面的「通用BLE偵錯工具」更近一步了!明天,我們將學習如何將這些邏輯模組化。
你能看到這裡,在這邊祝你早安、午安、晚安,我們明天見。


上一篇
DAY4:JavaScript 啟航:變數、資料型態與語言核心
下一篇
DAY6 :程式碼的模組化:函式、作用域與閉包
系列文
Web Bluetooth API 實戰:30 天打造通用 BLE 偵錯工具8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言