5【鸿蒙/OpenHarmony/NDK】使用Node-API进行异步任务开发

92 阅读5分钟

各位码友们好!今天这篇干货主要聚焦实操细节,希望能帮大家少踩坑。​
要是过程中遇到哪块没看懂、有疑问,或者你有更优的实现思路,评论区尽管聊!发现文档里有疏漏或错误也尽管指出来 ——
技术这东西就得互相挑刺才能越磨越精,咱们一起把这些知识点吃透~

是什么?

  • 与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。---百度百科
  • 用更加通俗的话说,举个例子,你去蛋糕店定做一个蛋糕。
    • 同步方式就是,你去蛋糕店告诉老板说你要一个蛋糕,然后老板开始做蛋糕,你就在店里等着,等老板做完,你带走蛋糕。
    • 异步就是,你去蛋糕店告诉老板说你要一个蛋糕,老板开始做蛋糕,你可以去逛街去购物,去做其他事情;老板做完蛋糕打电话给你,你过去把蛋糕拿回来。
    • 异步不会卡住当前线程,当前线程创建好异步任务就去干别的事情了,等异步任务完成在回来处理执行结果。

为什么?

  • 主要目的就一个,为了让我们的应用更加丝滑流畅,不卡顿。
    • HarmonyOS NEXT系统丝滑流畅,异步编程有着很大功劳。查阅HarmonyOS的API文档会发现很多耗时的API都是异步的。
    • 并且OpenHarmony的API设计规范里面也有一条这样的说明:应及时响应,避免调用者等待;如果API调用执行时间过长应设计为异步方式
  • 在需要执行耗时操作的场景中使用,避免阻塞env所在的ArkTS线程,确保应用程序的性能和响应性能。例如以下场景:
    • 文件操作:读取大型文件或执行复杂的文件操作时,可以使用异步工作对象来避免阻塞env所在的ArkTS线程。
    • 网络请求:当需要进行网络请求并等待响应时,使用异步工作对象确保主线程不被阻塞,提高应用程序的响应性能。
    • 数据库操作:当需要执行复杂的数据库查询或写入操作时,使用异步工作对象确保主线程不被阻塞,提高应用程序的并发性能。
    • 图像处理:当需要对大型图像进行处理或执行复杂的图像算法时,使用异步工作对象确保主线程不被阻塞,提高应用程序的实时性能。--- 华为开发者官网

怎么做?

不要在napi_create_async_work的execute回调中使用env变量

napi_status napi_create_async_work(napi_env env,
                                   napi_value async_resource,
                                   napi_value async_resource_name,
                                   napi_async_execute_callback execute,
                                   napi_async_complete_callback complete,
                                   void* data,
                                   napi_async_work* result);

execute函数应该避免进行任何可能导致执行JavaScript或与JavaScript对象交互的Node-API调用。大多数情况下,任何需要进行Node-API调用的代码都应该在complete回调中进行。避免在execute回调中使用napi_env参数,因为它可能会执行JavaScript。

不应该在complete回调中执行耗时任务

  • complete回调是用于将C++侧的结果转为js返回给应用。这个回调是在主线程中执行的,如果里面有耗时任务,则会占用主线程,导致出现应用卡住等问题,影响用户体验。
  • 所以建议complete里面只做语言类型的转换,不要有其他逻辑,其他逻辑尽可能放到execute中执行。

做好资源管理,避免泄漏

  • 我们存储上下文信息的data会被跨线程传递,所以不能使用栈内存,一定要申请动态内存。
  • 通常在调用napi_create_async_work创建异步任务之前,就应该申请好了data内存。
  • 然后在执行execute回调时,data会被传递过去,用于存放C++侧的上下文信息。
  • 接着执行complete时,也能够拿到data,我们就可以从data中取出C++的执行结果,然后转化成js语言。
  • 最后一定记得在complete回调中释放data内存,同时调用napi_delete_async_work删除异步任务。

在complete回调被调用之前,不应该删除napi_async_work

napi_status napi_cancel_async_work(node_api_basic_env env,
                                   napi_async_work work);

这个API会取消尚未执行的排队中的异步任务。如果任务已经开始执行,则不能取消,并且返回napi_generic_failure。如果成功,将调用complete回调,napi_status值为napi_cancelled。在完成complete回调之前,不应该删除napi_async_work,即使它已成功取消。

参考资料:

使用Node-API接口进行异步任务开发

Simple asynchronous operations

历史文章

1【鸿蒙/OpenHarmony/NDK】C/C++开发教程之环境搭建

2【鸿蒙/OpenHarmony/NDK】什么是NDK? 为啥要用NDK?

3【鸿蒙/OpenHarmony/NDK】如何在鸿蒙应用中使用NDK?

4【鸿蒙/OpenHarmony/NDK】如何在鸿蒙Navite C++样例代码中新增一个js接口?