写点什么

《HarmonyOSNext 性能暴增秘籍:Node-API 多线程通信从阻塞到丝滑的 4 大方案实战》

作者:Turing_010
  • 2025-06-16
    广东
  • 本文字数:10451 字

    阅读完需:约 34 分钟

《HarmonyOSNext性能暴增秘籍:Node-API多线程通信从阻塞到丝滑的4大方案实战》

《HarmonyOSNext 性能暴增秘籍:Node-API 多线程通信从阻塞到丝滑的 4 大方案实战》


##Harmony OS Next ##Ark Ts ##教育


本文适用于教育科普行业进行学习,有错误之处请指出我会修改。



🚀 引言:为啥要异步?搞懂线程才是王道!

兄弟姐妹们!做 Native 开发(尤其是 C/C++)的时候,有没有遇到过这种场景?🤔


👉 场景一: 算个超简单的数,主线程就想蹲那儿等结果立马用。这时候搞个同步开发,利索!🛸


👉 场景二: 碰到个计算怪兽🧟‍♂️(比如读超大文件、搞复杂图片处理),处理起来贼拉慢!这时候你还让主线程傻等?NoNoNo!主线程卡死了,App 界面动不了,用户立马想摔手机!💥


✅ 解决方案:上异步! 把这些耗时的脏活累活扔给 Native 侧的后台小线程去干!主线程该蹦迪蹦迪,该刷新 UI 刷新 UI,一点都不耽误!🕺💃


但是!问题来了❗️后台小线程干完活,结果怎么告诉主线程呢?主线程得用它来刷新界面呀(比如显示张刚加载好的帅照)!


别急!这就带大家撸一遍核心玩法:


  • 同步调用: 简单粗暴,主线程睡大觉等结果 💤

  • Callback 异步: 回头 call 你一下告诉你结果 📱

  • Promise 异步: 先给个承诺,干好了告诉你结果 🤝

  • 线程安全: 多个线程一起嗨,数据不乱跑 🧪🔒


本文就用一个超实用的图片加载案例,手把手教你咋玩转这四种模式!包会!😎



🗺️ 典型开发场景快速扫盲

先来个一分钟看懂几种玩法核心区别:



小提示💡: 同步也能带 Callback 哦!看开发者心情~ (主要看参数是否传了 Callback 函数)


下面深入讲讲我们的主角案例是怎么设计的!



🎮 案例登场:一个图片加载器搞定所有!

🧠 设计思路

目标:搞一个 UI,点不同按钮,用不同姿势(同步、callback、promise、线程安全)加载图片!还有个调皮按钮专门显示错误图片弹窗~ 😈


架构分成两大块:ArkTS 应用侧 + Native 侧。看图⬇️ (脑补效果图)


+-----------------------+       +-------------------------+|     ArkTS应用侧       |       |        Native侧          ||                       |       |                          || [同步按钮] [Callback] | ---> |    Native接口部分        || [Promise] [TSF]       |       |     🧐 核心逻辑处理!      ||                       |       |                          || +-------------------+ |       |                          || |     图片显示区      | | <---- |   生产者-消费者模型       || +-------------------+ |       |    (幕后大佬干重活!)     |+-----------------------+       +-------------------------+
复制代码

🪶 ArkTS 应用侧:点啥按钮,干啥活!

import testNapi from 'libentry.so'; // 引入我们写好的Native模块import Constants from '...'; // 路径常量
@Entry@Componentstruct Index { @State imagePath: string = Constants.INIT_IMAGE_PATH; // 默认图片路径 imageName: string = ''; // 要加载的图片名
build() { Column() { // ... (布局代码) Column() { // 1️⃣ 同步调用按钮 Button('多线程同步调用 🐢') // 🐢表示有点慢,主线程等 .onClick(() => { this.imageName = 'sync_img'; // 设置图片名 // ⚠️ 调用Native同步接口!界面在结果返回前会卡一下! this.imagePath = Constants.IMG_ROOT + testNapi.getImagePathSync(this.imageName); })
// 2️⃣ Callback异步按钮 Button('Callback异步 📱') .onClick(() => { this.imageName = 'callback_img'; // 调用异步接口,传入一个callback函数等着被call testNapi.getImagePathAsyncCallBack(this.imageName, (result: string) => { this.imagePath = Constants.IMG_ROOT + result; // Native干完会call这里! }); })
// 3️⃣ Promise异步按钮 Button('Promise异步 🤝') .onClick(() => { this.imageName = 'promise_img'; // 拿到一个Promise对象!用.then等结果 testNapi.getImagePathAsyncPromise(this.imageName).then((result: string) => { this.imagePath = Constants.IMG_ROOT + result; }); })
// 4️⃣ TSF线程安全异步按钮 Button('TSF线程安全 🔐') .onClick(() => { this.imageName = 'tsf_img'; // 也是callback接收结果,但底层用线程安全函数通信 testNapi.getImagePathAsyncTSF(this.imageName, (result: string) => { this.imagePath = Constants.IMG_ROOT + result; }); })
// 5️⃣ 调皮鬼按钮:错误图片测试 🐒 Button('错误图片测试 ❌') .onClick(() => { // 传入错误图片名,触发弹窗! this.imageName = 'wrong_img'; testNapi.getImagePathSync(this.imageName); // 这里调用哪个接口都可能触发 }) } // ... (显示图片的组件) } }}
复制代码

🦾 Native 侧:两大硬核组件发力!

  1. Native 接口部分: 接收 ArkTS 的命令,决定咋干活。

  2. 同步处理: 直接在当前线程(主线程!)上干活 -> 调生产者消费者模型找图 -> 返回结果给 ArkTS。

  3. 异步处理 (Callback/Promise/TSF): 创建异步任务(工作项或线程安全函数) -> 扔后台线程干 -> 干完想办法把结果传回 ArkTS 主线程刷新 UI。

  4. 生产者-消费者模型 (Producer-Consumer Model): 🧠 大脑级组件!负责最重的找图任务!

  5. 生产者线程🧵: 拿着图片名吭哧吭哧搜索🔍,找到路径放进一个缓冲队列

  6. 消费者线程🧵: 从队列里取路径结果,然后通过特定方法把结果传回 ArkTS 主线程🚀。


为啥用这个模型?🤔 完美协调“生产”和“消费”速度!队列满了生产等,队列空了消费等。信号量、条件变量、互斥锁上!安全又高效!✨

🧱 生产者-消费者模型核心实现 (Show me the code!)

关键文件头 (ProducerConsumer.h):


// ProducerConsumer.h#ifndef MULTITHREADS_PRODUCERCONSUMER_H#define MULTITHREADS_PRODUCERCONSUMER_H
#include <string>#include <queue>#include <mutex>#include <condition_variable>
using namespace std;
class ProducerConsumerQueue {public: // 构造函数,可以设置队列最大容量 ProducerConsumerQueue(int queueSize = 1) : m_maxSize(queueSize) {} // 默认容量1(一次处理一张图)
// ⭐ 生产者:把元素(图片路径)放进队列 void PutElement(string element);
// ⭐ 消费者:从队列里取出元素(图片路径) string TakeElement();
private: bool isFull() { return (m_queue.size() == m_maxSize); } // 队列满了吗? bool isEmpty() { return m_queue.empty(); } // 队列空了吗?
private: queue<string> m_queue{}; // 核心缓冲队列 int m_maxSize{}; // 队列最大容量 mutex m_mutex{}; // 🛡️ 互斥锁,保护队列操作安全! condition_variable m_notEmpty{}; // 😴 条件变量:通知"队列不空了!消费者快来取!" condition_variable m_notFull{}; // 😴 条件变量:通知"队列不满啦!生产者快来放!"};#endif
复制代码


具体实现 (ProducerConsumer.cpp):


// ProducerConsumer.cpp#include "ProducerConsumer.h"
// 生产者:放元素进队列void ProducerConsumerQueue::PutElement(string element) { unique_lock<mutex> lock(m_mutex); // 🔐 先加锁!
while (isFull()) { // 满了?老实等着消费者吃掉点腾地方! m_notFull.wait(lock); // 😴 等"不满"的信号(锁会自动释放) } // 不满了!把元素放进去,然后喊一嗓子:"不空啦!快来取!" m_queue.push(element); m_notEmpty.notify_one(); // 📣 唤醒一个等着的消费者}
// 消费者:从队列里拿元素string ProducerConsumerQueue::TakeElement() { unique_lock<mutex> lock(m_mutex); // 🔐 先加锁!
while (isEmpty()) { // 空的?老实等着生产者放点东西进来! m_notEmpty.wait(lock); // 😴 等"不空"的信号(锁自动释放) } // 不空了!拿走队头元素,然后喊一嗓子:"不满啦!快来放!" string element = m_queue.front(); m_queue.pop(); m_notFull.notify_one(); // 📣 唤醒一个等着的生产者 return element;}
复制代码

⚙️ Native 侧后台运作 (MultiThreads.cpp)

  1. 全局变量 & 搜索逻辑


// MultiThreads.cpp// 静态全局的缓冲队列实例(一次处理一张图,容量=1)static ProducerConsumerQueue buffQueue(1);
// 假装我们有这些图片路径(实际开发可能从数据库、网络、文件系统读取)static vector<string> imagePathVec{"sync.png", "callback.png", "promise.png", "tsf.png"};
// 辅助函数:检查图片路径名和输入名是否匹配(忽略后缀)static bool CheckImagePath(const string &imageName, const string &imagePath) { size_t pos = imagePath.find('.'); if (pos == string::npos) return false; // 无效路径 string nameOnly = imagePath.substr(0, pos); return (imageName == nameOnly); // 只比较名字部分}
// 🕵️‍♀️ 核心搜索函数:按图片名找路径static string SearchImagePath(const string &imageName) { for (const string &imgPath : imagePathVec) { if (CheckImagePath(imageName, imgPath)) { return imgPath; // 找到啦! } } return string(""); // 没找到!😢}
复制代码


  1. 生产者线程函数:找图塞队列


static void ProductElement(void *data) {    // 从上下文数据里拿到图片名,搜路径,放进队列    ContextData *ctx = static_cast<ContextData*>(data);    buffQueue.PutElement(SearchImagePath(ctx->args));}
复制代码



    消费者线程函数:取结果传回去


    • 普通异步(Callback/Promise):


    static void ConsumeElement(void *data) {    ContextData *ctx = static_cast<ContextData*>(data);    ctx->result = buffQueue.TakeElement(); // 从队列拿结果存起来(后续Native接口负责传回ArkTS)}*   **线程安全(TSF)异步:**static void ConsumeElementTSF(void *data) {    ContextData *ctx = static_cast<ContextData*>(data);    ctx->result = buffQueue.TakeElement();
    // 🔧 TSF关键步骤: // 1️⃣ 锁住线程安全函数(防止它在回调前被销毁) (void)napi_acquire_threadsafe_function(tsFun); // 2️⃣ 🔥 核心!把包含结果的数据和线程安全函数(tsFun)一起发给主线程EventLoop (void)napi_call_threadsafe_function(tsFun, data, napi_tsfn_blocking); // 阻塞模式确保发送成功 // 3️⃣ 释放TSF的引用 (void)napi_release_threadsafe_function(tsFun, napi_tsfn_release);}
    复制代码



    🔍 深入核心:四种模式怎么玩?

    🐢 模式 1:同步调用 - 简单直接但会卡一下

    📜 原理图脑补:


    ArkTS主线程(点击按钮) ---> [Native同步接口] ---> (主线程等) ---> 创建生产者/消费者线程并等它们干完活(join()) ---> 拿到结果返回 ---> ArkTS主线程刷新UI
    复制代码


    👨‍💻 Native 接口开发步骤 (MultiThreads.cpp):


    // ✨ 1. 导出接口给ArkTS用 (index.d.ts)export const getImagePathSync: (imageName: string) => string;
    // 📦 2. 上下文数据结构 (保存参数和结果)struct ContextData { // ... (可能有异步相关的成员,同步不用,但结构保持统一) string args = ""; // ArkTS传来的图片名 string result = ""; // 计算结果(图片路径)};
    // 🗑️ 3. 任务结束销毁上下文 (通用)static void DeleteContext(napi_env env, ContextData *ctx) { ... } // 略,见后面通用部分
    // 🧩 4. Native同步接口实现static napi_value GetImagePathSync(napi_env env, napi_callback_info info) { // ... (解析参数:图片名imageName)
    // 创建上下文数据 auto ctxData = new ContextData; ctxData->args = imageName;
    // 💪 同步干活:创建并等待生产者和消费者线程join完成! thread producer(ProductElement, static_cast<void*>(ctxData)); producer.join(); // 👉 主线程在这等生产者干完!
    thread consumer(ConsumeElement, static_cast<void*>(ctxData)); consumer.join(); // 👉 主线程在这等消费者干完!
    // 🎉 拿到结果了!转换成ArkTS能用的类型(string)返回 napi_value resultValue; napi_create_string_utf8(env, ctxData->result.c_str(), ctxData->result.length(), &resultValue);
    // 🧹 扫尾:删掉上下文数据 DeleteContext(env, ctxData);
    return resultValue; // ⬅️ 直接把这个值扔回给ArkTS主线程!}
    复制代码


    🌟 总结同步特点:

    • ArkTS 主线程调用后会"傻等"Native 计算完成。

    • Native 接口执行在 ArkTS 主线程

    • 生产者-消费者线程采用join()强制同步

    • 代码直观,但用户体验可能卡顿!谨慎用于耗时操作!

    📱 模式 2:Callback 异步 - 打完 Call 我!

    📜 原理图脑补:


    ArkTS主线程(点击按钮) --> [Native Callback接口] --> (立刻返回空值/null) --> ✅主线程继续爽滑操作UI                             ↓ (后台创建异步工作项入队)                    libuv线程池调度(work子线程) ---> execute回调干活(找图) ---> 主线程EventLoop ---> complete回调 ---> 执行你的Callback函数通知结果刷新UI
    复制代码


    👨‍💻 Native 接口开发步骤 (MultiThreads.cpp):


    // ✨ 1. 导出接口给ArkTS用 (index.d.ts)export const getImagePathAsyncCallBack: (imageName: string, callBack: (result: string) => void) => void;
    // 📦 2. 上下文数据结构 (重要!)struct ContextData { napi_async_work asyncWork = nullptr; // ✨异步工作项对象! napi_ref callbackRef = nullptr; // 🔗保存ArkTS传来的Callback函数的引用 string args = ""; string result = "";};
    // 🗑️ 3. 销毁上下文函数 (通用)static void DeleteContext(napi_env env, ContextData *ctx) { if (ctx->callbackRef) napi_delete_reference(env, ctx->callbackRef); // 🧹删Callback引用 if (ctx->asyncWork) napi_delete_async_work(env, ctx->asyncWork); // 🧹删异步工作项 delete ctx; // 🧹删上下文内存}
    // ⚙️ 4.1 execute回调 (libuv work子线程执行,不许碰napi!)static void ExecuteFunc([[maybe_unused]] napi_env env, void *data) { ContextData *ctx = static_cast<ContextData*>(data); // 干活:创建生产者消费者线程干活!⚠️必须在execute里join等它们干完! thread producer(ProductElement, data); producer.join(); thread consumer(ConsumeElement, data); consumer.join();}
    // 📨 4.2 complete回调 (主线程EventLoop执行,能调用napi!)static void CompleteFuncCallBack(napi_env env, [[maybe_unused]] napi_status status, void *data) { ContextData *ctx = static_cast<ContextData*>(data); // 1️⃣ 从引用里拿出ArkTS传的Callback函数 napi_value jsCallback; napi_get_reference_value(env, ctx->callbackRef, &jsCallback);
    // 2️⃣ 准备参数:计算结果(图片路径) napi_value callbackArg; napi_create_string_utf8(env, ctx->result.c_str(), ctx->result.length(), &callbackArg);
    // 3️⃣ 调用ArkTS的Callback函数!把结果传回去! napi_value undefined; napi_get_undefined(env, &undefined); // Callback的this用undefined napi_value ignore; napi_call_function(env, undefined, jsCallback, 1, &callbackArg, &ignore); // 调用Callback!
    // 4️⃣ 🧹 销毁上下文 DeleteContext(env, ctx);}
    // 🧩 5. Native Callback接口实现static napi_value GetImagePathAsyncCallBack(napi_env env, napi_callback_info info) { // ... (解析参数:imageName 和 callback函数)
    // 📦 创建并初始化上下文 auto ctxData = new ContextData; ctxData->args = imageName; napi_create_reference(env, callbackFunc, 1, &ctxData->callbackRef); // ⭐存Callback引用!
    // 🪄 创建异步工作项 (核心!) napi_value asyncName; napi_create_string_utf8(env, "AsyncCallBackJob", NAPI_AUTO_LENGTH, &asyncName); napi_create_async_work( // ⭐⭐关键API! env, nullptr, asyncName, ExecuteFunc, // 后台执行函数 CompleteFuncCallBack, // 完成回调函数(主线程) static_cast<void*>(ctxData), &ctxData->asyncWork // 返回的工作项对象存到ctx里 );
    // 🚀 把异步工作项扔进调度队列! napi_queue_async_work(env, ctxData->asyncWork);
    return nullptr; // ⚠️ 注意!立刻返回null给ArkTS!}
    复制代码


    🌟 总结 Callback 异步特点:

    • ArkTS 主线程调用后立刻返回null,丝滑流畅!🥰

    • 耗时活在 work 子线程(ExecuteFunc)做。

    • 结果在主线程的回调函数(CompleteFuncCallBack)中用napi_call_function调用 ArkTS 传的 Callback 通知。

    • 需要管理 Callback 函数引用和异步工作项生命周期。

    🤝 模式 3:Promise 异步 - 一言为定!

    📜 原理图脑补:


    ArkTS主线程(点击按钮) --> [Native Promise接口] --> (立刻返回Promise对象) --> ✅主线程爽滑操作,用.then等结果                             ↓ (后台创建异步工作项入队)                    libuv线程池调度(work子线程) ---> execute回调干活(找图) ---> 主线程EventLoop ---> complete回调 ---> napi_resolve_deferred通知Promise成功,触发.then刷新UI
    复制代码


    👨‍💻 Native 接口开发步骤 (MultiThreads.cpp):


    // ✨ 1. 导出接口给ArkTS用 (index.d.ts)export const getImagePathAsyncPromise: (imageName: string) => Promise<string>;
    // 📦 2. 上下文数据结构 (略改动)struct ContextData { napi_async_work asyncWork = nullptr; napi_deferred deferred = nullptr; // ✨新增!存Deferred对象 // ... (args, result)};
    // 🗑️ 3. 销毁上下文函数 (加删Deferred?不用删,napi自己管)
    // ⚙️ 4.1 execute回调 (work子线程做,同Callback模式)static void ExecuteFunc([[maybe_unused]] napi_env env, void *data) { ... // 同Callback的ExecuteFunc(干活:找图)}
    // ✅ 4.2 complete回调 (主线程执行)static void CompleteFuncPromise(napi_env env, [[maybe_unused]] napi_status status, void *data) { ContextData *ctx = static_cast<ContextData*>(data); // 准备结果值 (图片路径) napi_value resolveValue; napi_create_string_utf8(env, ctx->result.c_str(), ctx->result.length(), &resolveValue);
    // 🔥 核心!用Deferred对象通知Promise成功啦! napi_resolve_deferred(env, ctx->deferred, resolveValue);
    // 🧹 销毁上下文 DeleteContext(env, ctx);}
    // 🧩 5. Native Promise接口实现static napi_value GetImagePathAsyncPromise(napi_env env, napi_callback_info info) { // ... (解析参数:imageName)
    // 📦 创建上下文 auto ctxData = new ContextData; ctxData->args = imageName;
    // 🪄 创建异步工作项 (同Callback) napi_value asyncName; ... // 略 napi_create_async_work(env, nullptr, asyncName, ExecuteFunc, CompleteFuncPromise, static_cast<void*>(ctxData), &ctxData->asyncWork);
    // 🔮 核心!创建Promise对象及其关联的Deferred napi_value promiseObj; napi_create_promise(env, &ctxData->deferred, &promiseObj); // ⭐ctxData->deferred存关键对象
    // 🚀 入队异步工作项 napi_queue_async_work(env, ctxData->asyncWork);
    return promiseObj; // ⬅️ 把刚创建的Promise对象立刻返回给ArkTS!}
    复制代码


    🌟 总结 Promise 异步特点:

    • ArkTS 主线程调用后立刻返回一个Promise对象。

    • 耗时活在 work 子线程(ExecuteFunc)做。

    • 结果在主线程的回调函数(CompleteFuncPromise)中用napi_resolve_deferred通知 Promise 成功,这会触发 ArkTS 的.then

    • 代码风格更现代(链式调用),逻辑清晰。

    🔐 模式 4:线程安全(TSF) - 多线程不打架!

    📜 原理图脑补:


    ArkTS主线程(点击按钮) --> [Native TSF接口] --> (立刻返回空/null) --> ✅主线程继续爽滑                             ↓ (初始化TSF绑定Callback + 后台起线程)                    生产者线程🧵 ---> 找图塞队列                    消费者线程🧵 ---> 1. 取结果 2. napi_call_threadsafe_function 🚀把结果+回调任务扔给主线程EventLoop                        主线程EventLoop调度 ---> 执行CallJsFunction ---> 调用ArkTS的Callback函数通知结果刷新UI
    复制代码


    👨‍💻 Native 接口开发步骤 (MultiThreads.cpp):


    // ✨ 1. 导出接口给ArkTS用 (index.d.ts) (和Callback异步签名类似)export const getImagePathAsyncTSF: (imageName: string, callBack: (result: string) => void) => void;
    // 📦 2. 全局线程安全函数对象static napi_threadsafe_function tsFun = nullptr; // ⚠️全局!通常是单例!
    // 🧩 3.1 CallJs回调(由EventLoop在主线程调度执行)static void CallJsFunction(napi_env env, napi_value jsCallback, [[maybe_unused]] void *context, void *data) { ContextData *ctx = static_cast<ContextData*>(data); // 结果转换 (同Callback completeFunc) napi_value callbackArg; napi_create_string_utf8(env, ctx->result.c_str(), ctx->result.length(), &callbackArg);
    // 调用ArkTS的Callback! napi_value undefined; napi_get_undefined(env, &undefined); napi_value ignore; napi_call_function(env, undefined, jsCallback, 1, &callbackArg, &ignore);
    // 🧹 销毁传入的上下文数据 DeleteContext(env, ctx);}
    // 🧩 3.2 Native TSF接口实现static napi_value GetImagePathAsyncTSF(napi_env env, napi_callback_info info) { // ... (解析参数:imageName, callback)
    // 📦 创建上下文 (存参数和结果) auto ctxData = new ContextData; ctxData->args = imageName; // ❗️注意:这个contextData会在CallJsFunction里销毁,不在这里存callbackRef!
    // ⚡ 核心1:创建线程安全函数(TSF) (通常首次调用时创建) if (tsFun == nullptr) { constexpr int MAX_QUEUE = 0; // 队列无限大(不阻塞) constexpr int INIT_THREADS = 1; napi_value asyncName; ... // 创建异步资源名略
    napi_create_threadsafe_function( // ⭐⭐关键API! env, callbackFunc, // 🔗ArkTS传的Callback函数 nullptr, // async_resource (可空) asyncName, // async_resource_name MAX_QUEUE, // max_queue_size (0=无限) INIT_THREADS, // initial_thread_count nullptr, // thread_finalize_data nullptr, // thread_finalize_cb nullptr, // context CallJsFunction, // 🔥 call_js_cb (关键!主线程调用的函数) &tsFun // 🔥 返回的线程安全函数对象存全局 ); }
    // ⚡ 核心2:直接创建后台干活线程 (生产者 & 消费者) // 1. 生产者线程:ProductElement(ctxData) thread producer(ProductElement, static_cast<void*>(ctxData)); producer.detach(); // ❗️非常重要!让线程独立运行,不阻塞当前线程(TSF接口主线程)
    // 2. 消费者线程:ConsumeElementTSF(ctxData) (内部会调napi_call_threadsafe_function!) thread consumer(ConsumeElementTSF, static_cast<void*>(ctxData)); consumer.detach(); // ❗️同样detach!
    return nullptr; // ⚠️ 立即返回null!}
    复制代码


    🌟 总结 TSF 异步特点:

    • ArkTS 调用后立刻返回null

    • 核心机制是全局的napi_threadsafe_function (tsFun)。

    • 直接在 Native 后台线程(C++线程,非 libuv work 线程)干活! 消费者线程主动调用napi_call_threadsafe_function将任务和结果“推”给主线程 EventLoop。

    • EventLoop 在主线程调用CallJsFunction,最终调用 ArkTS 的 Callback。

    • 更底层灵活,适用于非 work 子线程的复杂多线程场景。

    • 需要管理全局 TSF 生命周期(通常随模块存在),后台线程detach防止阻塞 TSF 接口调用线程。



    🎯 总结:选谁?看场景!

    经过这么一大轮学习,咱们最后做个超级清晰的区别对比!存好这张表!🧾



    选型小贴士:


    1. 能用异步不用同步! 用户体验第一位!🥇

    2. 简单异步任务: CallbackPromise 都很棒!Promise更现代。

    3. 需要精细控制线程或与非 libuv 线程通信: TSF 是不二之选!🧠🔧

    4. 结果影响 UI: 确保在 .then()Callback 里更新 UI!否则报错!⚠️


    搞定!把这四种模式的玩法彻底搞清楚了!🎉🎉 快去给你的应用加点丝滑的异步魔法吧!✨

    用户头像

    Turing_010

    关注

    还未添加个人签名 2025-05-22 加入

    还未添加个人简介

    评论

    发布
    暂无评论
    《HarmonyOSNext性能暴增秘籍:Node-API多线程通信从阻塞到丝滑的4大方案实战》_Turing_010_InfoQ写作社区