如何在Native侧调用ArkTS侧异步方法,并获取异步计算结果到Native侧

如何在Native侧调用ArkTS侧异步方法,并获取异步计算结果到Native侧

HarmonyOS
2024-03-19 16:24:07
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
kaijunx

该场景诉求可以通过在Native侧获取ArkTS侧Promise对象来实现。具体步骤如下:

  •  ArkTS侧实现:

a. 调用Native接口时,传入callback回调。在该回调中通过构造函数创建Promise对象;

b. 在Promise构造函数的参数回调中,实现异步操作,并根据操作结果,调用resolve或者reject接口,用以对Promise对象进行状态迁移。

  •  Native侧实现:

a. 定义Promise对象then属性的回调方法,用以处理ArkTS侧异步计算结果;

b. 定义Promise对象catch属性的回调方法,用以处理ArkTS侧异步计算异常信息;

c. 在Native接口实现中,通过napi_call_function接口执行ArkTS侧传入的callback回调,获取Promise对象;

d. 通过napi_get_named_property接口获取Promise对象中的then和catch属性;

e. 通过napi_create_function接口将上述定义的then和catch属性C++回调方法转换为ArkTS函数对象;

f. 通过napi_call_function接口执行then和catch属性对应ArkTS函数对象,用以处理ArkTS侧的异步计算结果和异常信息。类似于在ArkTS侧调用promise.then(()=>{}和promise.catch(()=>{}。

具体可参考以下示例代码:

(一)ArkTS侧实现

// ... 
import testNapi from 'libentry.so'; 
 
@Entry 
@Component 
struct Index { 
  build() { 
    Row() { 
      Column() { 
        Text('testPromise') 
          // ... 
          .onClick(() => { 
            hilog.info(0x0000, 'testTag-ArkTS', 'Before calling the native interface.'); 
            // 调用Native接口,返回调用信息 
            testNapi.testPromise(() => { 
                // callback回调用于创建ArkTS侧Promise对象 
                return new Promise((resolve: Function, reject: Function) => { 
                  // 通过setTimeout接口模拟ArkTS侧异步方法 
                  // 场景:2秒后,触发setTimeout定时器回调,生产一个随机数randomNumber,通过判断随机数的大小,用于触发promise对象不同状态,继而进行不同回调处理 
                  setTimeout(()=>{ 
                    const randomNumber: number = 100 * Math.random(); 
                    if (randomNumber > 50) { 
                      // 如果randomNumber大于50,则调用resolve方法,将Promise对象的状态转移到fulfilled状态,并将随机数传递到Native侧,作为then方法的回调参数 
                      resolve(randomNumber); 
                    } else { 
                      // 如果randomNumber小于/等于50,则调用reject方法,将Promise对象的状态转移到rejected状态,并将异常信息传递到Native侧,作为catch方法的回调参数 
                      reject('The random number is less than 50, so the promise object is rejected.') 
                    } 
                  }, 2000); 
                }) 
              } 
            ) 
            hilog.info(0x0000, 'testTag-ArkTS', 'After the native interface is called.'); 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

(二)Native侧实现

#include "napi/native_api.h" 
#include "hilog/log.h" 
 
// 定义Promise对象then属性的回调方法 
// then属性的回调方法可以无返回值 
// 后文需要通过napi_create_function创建ArkTS函数对象,所以设置返回值为napi_value,并在函数末尾返回nullptr 
napi_value ThenCallBack(napi_env env, napi_callback_info info) { 
    size_t argc = 1; 
    napi_value args[1] = {nullptr}; 
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 
    int32_t asyncResult = 0; // ArkTS侧异步方法计算结果 
    napi_get_value_int32(env, args[0], &asyncResult); 
    OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "testTag-Native", "ArkTS Async Method Calculation Success, Result: %{public}d", 
                 asyncResult); 
    return nullptr; 
} 
// 定义Promise对象catch属性的回调方法 
// catch属性的回调方法可以无返回值 
// 后文需要通过napi_create_function创建ArkTS函数对象,所以设置返回值为napi_value,并在函数末尾返回nullptr 
napi_value CatchCallBack(napi_env env, napi_callback_info info) { 
    size_t argc = 1; 
    napi_value args[1] = {nullptr}; 
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 
    size_t strLen = 0; 
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &strLen);            // 获取字符串长度到strLen 
    char *strBuffer = new char[strLen + 1];                                   // 分配合适大小的char数组 
    napi_get_value_string_utf8(env, args[0], strBuffer, strLen + 1, &strLen); // 获取字符串,表示ArkTS侧异步方法计算异常的信息 
    OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "testTag-Native", 
                 "ArkTS Async Method Calculation Exception: %{public}s", strBuffer); 
    return nullptr; 
} 
static napi_value TestPromise(napi_env env, napi_callback_info info) { 
    size_t argc = 1; 
    napi_value args[1] = {nullptr}; 
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); // 解析ArkTS侧传入的回调callback 
 
    napi_value arktsPromise = nullptr; 
    // 通过napi_call_function执行callback,返回ArkTS侧创建的promise对象 
    napi_call_function(env, nullptr, args[0], 0, nullptr, &arktsPromise); 
 
    // 获取promise对象的then属性,该属性的回调方法用于处理ArkTS侧异步计算结果 
    napi_value thenProperty = nullptr; 
    napi_get_named_property(env, arktsPromise, "then", &thenProperty); 
    // 将C++语言定义的then属性回调方法转换为ArkTS函数对象,即napi_value类型值 
    napi_value thenCallback = nullptr; 
    napi_create_function(env, "thenCallback", NAPI_AUTO_LENGTH, ThenCallBack, nullptr, &thenCallback); 
 
    // 获取promise对象的catch属性,该属性的回调方法用于处理ArkTS侧异步计算异常的信息 
    napi_value catchProperty = nullptr; 
    napi_get_named_property(env, arktsPromise, "catch", &catchProperty); 
    // 将C++语言定义的catch属性回调方法转换为ArkTS函数对象,即napi_value类型值 
    napi_value catchCallback = nullptr; 
    napi_create_function(env, "catchCallback", NAPI_AUTO_LENGTH, CatchCallBack, nullptr, &catchCallback); 
     
    // 通过napi_call_function执行then属性的回调,类似于ArkTS侧调用promise.then(()=>{}) 
    napi_call_function(env, arktsPromise, thenProperty, 1, &thenCallback, nullptr); 
    // 通过napi_call_function执行catch属性的回调,类似于ArkTS侧调用promise.catch(()=>{}) 
    napi_call_function(env, arktsPromise, catchProperty, 1, &catchCallback, nullptr); 
    return nullptr; 
}

运行结果

  • 结果(1)表示ArkTS侧调用Native接口后,Native侧运行并未阻塞,直接返回。
  • 结果(2)表示ArkTS侧调用Native接口后,等待2秒(异步计算),因为异步操作中生产的随机数小于等于50,所以通过Promise对象的reject接口传入异常信息到Native侧,并通过catch回调进行显示处理。
  • 结果(3)表示ArkTS侧调用Native接口后,等待2秒(异步计算),因为异步操作中生产的随机数大于50,所以通过Promise对象的resolve接口传入随机数到Native侧,并通过then回调进行显示处理。
已于2024-3-20 00:02:17修改
分享
微博
QQ
微信
回复
2024-03-20 00:01:56
相关问题
如何在Native释放ArkTS对象
246浏览 • 1回复 待解决
如何在Native获取APP版本信息
204浏览 • 1回复 待解决
如何在Native构建一个ArkTS对象
202浏览 • 1回复 待解决
ArkTSNative如何进行map数据交互
209浏览 • 1回复 待解决
Native如何打印char指针
197浏览 • 1回复 待解决
Native如何获取可操作的文件目录
154浏览 • 1回复 待解决
Native创建线程是否有限制
239浏览 • 1回复 待解决
Native如何引入头文件deviceinfo.h
211浏览 • 1回复 待解决
Native如何使用hilog打印出日志信息
159浏览 • 1回复 待解决
Native如何集成三方SO库
180浏览 • 1回复 待解决
Native如何ArkTS方法
254浏览 • 1回复 待解决
设备同步及云相关问题
7562浏览 • 3回复 待解决