ArkTS異步編程全解析:從async/await到Actor模型

2024-12-04 09:46 更新

大家好,我是 V 哥,很好奇,在ArkTS中實現(xiàn)異步編程是怎樣的,今天的內(nèi)容來聊聊這個問題,總結(jié)了一些學習筆記,分享給大家,在 ArkTS中實現(xiàn)異步編程主要可以通過以下幾種方式:

1. 使用asyncawait關(guān)鍵字

async函數(shù)是一種特殊的函數(shù),它能以同步代碼的方式編寫異步代碼。在async函數(shù)內(nèi)部,可以使用await表達式來等待一個異步操作返回一個Promise對象。這種方式可以讓異步代碼的編寫和閱讀更接近同步代碼的風格,提高代碼的可讀性和可維護性。

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

async函數(shù)和await關(guān)鍵字有什么區(qū)別?

asyncawait 是 JavaScript 中用于異步編程的兩個關(guān)鍵字,它們共同工作以簡化異步代碼的編寫和理解,但它們各自有不同的用途和含義:

async 關(guān)鍵字

  • async 是一個用于聲明異步函數(shù)的關(guān)鍵字。
  • 任何使用 async 聲明的函數(shù)都會自動返回一個 Promise 對象。
  • 如果函數(shù)正常執(zhí)行結(jié)束,Promise 將被解決(resolve)并返回函數(shù)的返回值。
  • 如果函數(shù)中拋出錯誤,Promise 將被拒絕(reject)。
  • async 函數(shù)內(nèi)部可以包含一個或多個 await 表達式。

await 關(guān)鍵字

  • await 是一個用于等待一個 Promise 對象解決(resolve)的關(guān)鍵字。
  • await 只能在 async 函數(shù)內(nèi)部使用。
  • 當執(zhí)行到 await 表達式時,JavaScript 引擎會暫停該 async 函數(shù)的執(zhí)行,直到等待的 Promise 被解決。
  • 如果 Promise 被解決,await 表達式返回 Promise 的值。
  • 如果 Promise 被拒絕,await 表達式會拋出拒絕的原因,這可以通過 try...catch 語句捕獲。
  • await 后面通常跟的是一個異步操作,比如一個返回 Promise 的函數(shù)調(diào)用。

它們的區(qū)別

  • async 是用來聲明函數(shù)的,而 await 是用來在函數(shù)內(nèi)部等待異步操作的。
  • async 本身不暫停代碼執(zhí)行,它只是讓函數(shù)返回一個 Promise;而 await 是用來暫停代碼執(zhí)行,直到 Promise 被解決。
  • async 可以不與 await 一起使用,這時函數(shù)仍然返回一個 Promise,但不會暫停執(zhí)行。
  • await 必須用在 async 函數(shù)內(nèi)部,否則會拋出語法錯誤。

示例

// async 函數(shù)聲明
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 用于聲明異步函數(shù),而 await 用于在異步函數(shù)內(nèi)部等待異步操作的完成,初學者需要注意不要混淆了。

2. 使用Promise對象

上面我們已經(jīng)提到Promise對象了,Promise是處理異步操作的對象,它提供了一個狀態(tài)機制來管理異步操作的不同階段,代表一個異步操作的最終完成(或失?。┘捌浣Y(jié)果值,并提供了一些方法來注冊回調(diào)函數(shù)以處理異步操作的成功或失敗的結(jié)果。Promise有三種狀態(tài):pending(進行中)、fulfilled(已完成)和rejected(已拒絕)。

// 創(chuàng)建一個新的Promise
const myPromise = new Promise((resolve, reject) => {
  // 異步操作
  if (/* 異步操作成功 */) {
    resolve("Success");
  } else {
    reject("Error");
  }
});


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

3. 異常處理

在異步函數(shù)中,如果出現(xiàn)錯誤,可以通過try...catch語句來捕獲異常。

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

4. 并發(fā)執(zhí)行異步任務(wù)

可以使用Promise.all來并發(fā)執(zhí)行多個異步任務(wù),并等待它們?nèi)客瓿伞?/p>

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

5. 使用Actor模型

ArkTS語言采用的Actor模型是一種并發(fā)編程模型,其中每個Actor都是一個獨立的計算單元,擁有自己的狀態(tài)和行為,并通過消息傳遞與其他Actor進行通信和協(xié)作。

1. Actor模型概述

在Actor模型中,每個Actor都可以接收異步消息,并根據(jù)消息內(nèi)容和當前狀態(tài)做出響應。Actor之間的消息傳遞是異步的,發(fā)送消息的Actor不需要等待接收消息的Actor的響應,從而實現(xiàn)并發(fā)執(zhí)行。由于每個Actor都是獨立的,它們之間不存在共享狀態(tài),因此不需要進行鎖機制和同步操作,避免了一些常見的并發(fā)編程問題,如死鎖和競爭條件。

2. 數(shù)據(jù)傳輸對象

ArkTS語言支持傳輸?shù)臄?shù)據(jù)對象可以分為四種:普通對象、可轉(zhuǎn)移對象、可共享對象和Native綁定對象。普通對象的傳輸是通過結(jié)構(gòu)化克隆算法進行序列化的,支持多種類型,包括基礎(chǔ)類型、Date、String、RegExp、Array、Map、Set等。

3. 實現(xiàn)例子

以下是一個使用ArkTS的Actor模型實現(xiàn)的生產(chǎn)者消費者問題的示例:

生產(chǎn)者(Producer)和消費者(Consumer)的Actor模型實現(xiàn):

import taskpool from '@ohos.taskpool';


// 跨線程并發(fā)任務(wù)
@Concurrent
async function produce(): Promise<number>{
  // 添加生產(chǎn)相關(guān)邏輯
  console.log("test producing...");
  return Math.random();
}


class Consumer {
  public consume(value: number) {
    // 添加消費相關(guān)邏輯
    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++) {
            // 執(zhí)行生產(chǎn)異步并發(fā)任務(wù)
            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 函數(shù)是一個異步函數(shù),模擬生產(chǎn)者的生產(chǎn)過程,并返回一個隨機數(shù)作為產(chǎn)品。Consumer 類包含 consume 方法,用于消費產(chǎn)品。在UI界面上,當用戶點擊“start”按鈕時,會啟動10次生產(chǎn)任務(wù),每次生產(chǎn)任務(wù)完成后,都會調(diào)用Consumerconsume方法來消費產(chǎn)品。

這個例子展示了如何在ArkTS中使用Actor模型來實現(xiàn)并發(fā)執(zhí)行,其中生產(chǎn)者和消費者之間通過異步消息傳遞來通信,無需等待對方的響應,從而實現(xiàn)高效的并發(fā)處理。

最后

ArkTS提供了強大的異步編程能力,使得開發(fā)者可以有效地處理異步任務(wù),提高程序的性能和響應能力。對于有 TypeScript 經(jīng)驗的兄弟是不是有種找到真愛的感覺呢。關(guān)注威哥愛編程,鴻蒙開天辟地,你我皆是同路人。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號