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

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

阅读 4.4k
1 个回答

该场景诉求可以通过在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; 
}

运行结果

image.png

结果(1):表示ArkTS侧调用Native接口后,Native侧运行并未阻塞,直接返回。

结果(2):表示ArkTS侧调用Native接口后,等待2秒(异步计算),因为异步操作中生产的随机数小于等于50,所以通过Promise对象的reject接口传入异常信息到Native侧,并通过catch回调进行显示处理。

结果(3):表示ArkTS侧调用Native接口后,等待2秒(异步计算),因为异步操作中生产的随机数大于50,所以通过Promise对象的resolve接口传入随机数到Native侧,并通过then回调进行显示处理。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进