非同步程式設計在ArkTS中具體怎麼實現?

威哥爱编程發表於2024-11-21

大家好,我是 V 哥,很好奇,在ArkTS中實現非同步程式設計是怎樣的,今天的內容來聊聊這個問題,總結了一些學習筆記,分享給大家,在 ArkTS中實現非同步程式設計主要可以透過以下幾種方式:

1. 使用asyncawait關鍵字

async函式是一種特殊的函式,它能以同步程式碼的方式編寫非同步程式碼。在async函式內部,可以使用await表示式來等待一個非同步操作返回一個Promise物件。這種方式可以讓非同步程式碼的編寫和閱讀更接近同步程式碼的風格,提高程式碼的可讀性和可維護性。

// 定義一個async函式
async function myAsyncFunction() {
  // 使用await等待非同步操作完成
  const result = await someAsyncOperation();
  console.log(result);
}

async函式和await關鍵字有什麼區別?

asyncawait 是 JavaScript 中用於非同步程式設計的兩個關鍵字,它們共同工作以簡化非同步程式碼的編寫和理解,但它們各自有不同的用途和含義:

async 關鍵字

  • async 是一個用於宣告非同步函式的關鍵字。
  • 任何使用 async 宣告的函式都會自動返回一個 Promise 物件。
  • 如果函式正常執行結束,Promise 將被解決(resolve)並返回函式的返回值。
  • 如果函式中丟擲錯誤,Promise 將被拒絕(reject)。
  • async 函式內部可以包含一個或多個 await 表示式。

await 關鍵字

  • await 是一個用於等待一個 Promise 物件解決(resolve)的關鍵字。
  • await 只能在 async 函式內部使用。
  • 當執行到 await 表示式時,JavaScript 引擎會暫停該 async 函式的執行,直到等待的 Promise 被解決。
  • 如果 Promise 被解決,await 表示式返回 Promise 的值。
  • 如果 Promise 被拒絕,await 表示式會丟擲拒絕的原因,這可以透過 try...catch 語句捕獲。
  • await 後面通常跟的是一個非同步操作,比如一個返回 Promise 的函式呼叫。

它們的區別

  • async 是用來宣告函式的,而 await 是用來在函式內部等待非同步操作的。
  • async 本身不暫停程式碼執行,它只是讓函式返回一個 Promise;而 await 是用來暫停程式碼執行,直到 Promise 被解決。
  • async 可以不與 await 一起使用,這時函式仍然返回一個 Promise,但不會暫停執行。
  • await 必須用在 async 函式內部,否則會丟擲語法錯誤。

示例

// async 函式宣告
async function fetchData() {
  // 等待非同步操作完成
  const data = await fetchSomeData(); // 這裡使用了 await
  return data;
}

// 單獨使用 async
async function justAsync() {
  console.log('This is an async function, but without await.');
}

// 使用 await
async function useAwait() {
  console.log('Before await.');
  await justAsync(); // 等待 justAsync 完成
  console.log('After await.');
}

所以啊, V哥提醒一下,asyncawait 是非同步程式設計中兩個互補的概念,async 用於宣告非同步函式,而 await 用於在非同步函式內部等待非同步操作的完成,初學者需要注意不要混淆了。

2. 使用Promise物件

上面我們已經提到Promise物件了,Promise是處理非同步操作的物件,它提供了一個狀態機制來管理非同步操作的不同階段,代表一個非同步操作的最終完成(或失敗)及其結果值,並提供了一些方法來註冊回撥函式以處理非同步操作的成功或失敗的結果。Promise有三種狀態:pending(進行中)、fulfilled(已完成)和rejected(已拒絕)。

// 建立一個新的Promise
const myPromise = new Promise((resolve, reject) => {
  // 非同步操作
  if (/* 非同步操作成功 */) {
    resolve("Success");
  } else {
    reject("Error");
  }
});

// 使用then和catch處理Promise的結果
myPromise.then((value) => {
  console.log(value); // "Success"
}).catch((error) => {
  console.error(error); // "Error"
});

3. 異常處理

在非同步函式中,如果出現錯誤,可以透過try...catch語句來捕獲異常。

async function myAsyncFunction() {
  try {
    const result = await someAsyncOperation();
    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

4. 併發執行非同步任務

可以使用Promise.all來併發執行多個非同步任務,並等待它們全部完成。

async function concurrentTasks() {
  const [result1, result2] = await Promise.all([
    asyncOperation1(),
    asyncOperation2()
  ]);
  console.log(result1, result2);
}

5. 使用Actor模型

ArkTS語言採用的Actor模型是一種併發程式設計模型,其中每個Actor都是一個獨立的計算單元,擁有自己的狀態和行為,並透過訊息傳遞與其他Actor進行通訊和協作。

1. Actor模型概述

在Actor模型中,每個Actor都可以接收非同步訊息,並根據訊息內容和當前狀態做出響應。Actor之間的訊息傳遞是非同步的,傳送訊息的Actor不需要等待接收訊息的Actor的響應,從而實現併發執行。由於每個Actor都是獨立的,它們之間不存在共享狀態,因此不需要進行鎖機制和同步操作,避免了一些常見的併發程式設計問題,如死鎖和競爭條件。

2. 資料傳輸物件

ArkTS語言支援傳輸的資料物件可以分為四種:普通物件、可轉移物件、可共享物件和Native繫結物件。普通物件的傳輸是透過結構化克隆演算法進行序列化的,支援多種型別,包括基礎型別、Date、String、RegExp、Array、Map、Set等。

3. 實現例子

以下是一個使用ArkTS的Actor模型實現的生產者消費者問題的示例:

生產者(Producer)和消費者(Consumer)的Actor模型實現:

import taskpool from '@ohos.taskpool';

// 跨執行緒併發任務
@Concurrent
async function produce(): Promise<number>{
  // 新增生產相關邏輯
  console.log("test producing...");
  return Math.random();
}

class Consumer {
  public consume(value: number) {
    // 新增消費相關邏輯
    console.log("test consuming value: " + value);
  }
}

@Entry
@Component
struct Index {
  @State message: string = 'Hello I am VG';
  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
        Button() {
          Text("start")
        }.onClick(() => {
          let produceTask: taskpool.Task = new taskpool.Task(produce);
          let consumer: Consumer = new Consumer();
          for (let index: number = 0; index < 10; index++) {
            // 執行生產非同步併發任務
            taskpool.execute(produceTask).then((res: number) => {
              consumer.consume(res);
            }).catch((e: Error) => {
              console.error(e.message);
            })
          }
        })
        .width('20%')
        .height('20%')
      }
      .width('100%')
    }
    .height('100%')
  }
}

在這個例子中,produce 函式是一個非同步函式,模擬生產者的生產過程,並返回一個隨機數作為產品。Consumer 類包含 consume 方法,用於消費產品。在UI介面上,當使用者點選“start”按鈕時,會啟動10次生產任務,每次生產任務完成後,都會呼叫Consumerconsume方法來消費產品。

這個例子展示瞭如何在ArkTS中使用Actor模型來實現併發執行,其中生產者和消費者之間透過非同步訊息傳遞來通訊,無需等待對方的響應,從而實現高效的併發處理。

最後

ArkTS提供了強大的非同步程式設計能力,使得開發者可以有效地處理非同步任務,提高程式的效能和響應能力。對於有 TypeScript 經驗的兄弟是不是有種找到真愛的感覺呢。關注威哥愛程式設計,鴻蒙開天闢地,你我皆是同路人。

相關文章