[求助] HarmonyOS鸿蒙Next中runJavaScript运行异步JS代码的结果获取

[求助] HarmonyOS鸿蒙Next中runJavaScript运行异步JS代码的结果获取 我有一段JavaScript代码(省略细节)如下

function waitForValue() {
  return new Promise((resolve, reject) => {...});
}

(async () => {
  try {
    const val = await waitForValue();
    return val;
  } catch (e) {
    console.error(e);
  }
})();

经浏览器测试可以正常工作。但是在ArkTS中

this.webviewController.runJavaScript(code)
  .then((resolvedResult) => {console.log(resolvedResult);})

在控制台打印出来的是null。请问如何解决?


更多关于[求助] HarmonyOS鸿蒙Next中runJavaScript运行异步JS代码的结果获取的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

你好,runJavaScript 执行的js方法,如果是异步方法将无法获取返回值。

可以借助 javaScriptProxy 代理对象来获取异步方法的执行结果。

大致思路是:

1、注册代理对象,名为testObjName,该对象有一个test方法。

2、执行异步js方法的结果val, 作为test方法的参数传递。

3、在test方法中获取执行结果。

import { webview } from '@kit.ArkWeb';

class TestClass {
  test(param: ESObject): void {
    console.log(param) // xianyin
  }
}

@Entry
@Component
struct Index {
  webviewController: webview.WebviewController = new webview.WebviewController();
  @State testObj: TestClass = new TestClass();

  build() {
    Column() {
      Button('run')
        .onClick(() => {
          this.onRun()
        })
      Web({ src: $rawfile('index.html'), controller: this.webviewController })
        .javaScriptProxy({
          object: this.testObj,
          name: "testObjName",
          methodList: ["test"],
          controller: this.webviewController,
        })
    }
    .margin({ top: 100 })
  }

  onRun() {
    const js = `
    function waitForValue() {
      return new Promise((resolve, reject) => { return  resolve('xianyin') });
    }
    (async () => {
       const val = await waitForValue();
       testObjName.test(val)
    })()
    `
    this.webviewController.runJavaScript(js) //执行结果在test()中返回
  }
}

更多关于[求助] HarmonyOS鸿蒙Next中runJavaScript运行异步JS代码的结果获取的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


数据传递建议使用序列化成JSON字符串的形式,然后再使用console.log()进行打印,若数据传输正常,再使用反序列化拿到数据;

JSON.stringify(data);//序列化成JSON字符串进行数据传输
JSON.parse(dataJson); //反序列后拿到数据

Webview的runJavaScript和runJavaScriptExt二者均可异步执行JavaScript脚本,并通过回调或Promise返回执行结果。

区别上讲,runJavaScript返回脚本执行的结果只能是string,而runJavaScriptExt可以返回的类型支持JsMessageType,包括字符串、数组类型等。

另外,如果这个HTML是你自己的项目,建议将复杂的js代码直接封装到HTML页面中,只暴露出函数名就行了,然后runJavaScript 的时候就轻松多了!

经过测试我推测runJavaScript的回调在JS同步执行完后就触发了,等不到异步的结果(但我未在官方文档中找到相关说明) 你能不能给一个成功执行异步JavaScript的完整例子?谢谢!

在HarmonyOS Next中,使用runJavaScript执行异步JavaScript代码时,可通过JavaScriptResult回调获取结果。异步操作需在JS代码中返回Promise,系统会等待Promise解析后,在回调中返回最终结果或错误。

在HarmonyOS Next中,WebviewController.runJavaScript() 方法默认返回的是所执行脚本中 最后一条表达式 的值。你的异步JavaScript代码是一个立即执行的异步函数表达式(IIFE),它返回的是一个Promise对象,但runJavaScript并不会自动等待这个Promise完成并解析其最终值。

要获取异步JavaScript代码的最终结果,你需要让脚本明确地返回一个Promise,并且ArkTS端需要处理这个Promise的解析。具体方法如下:

1. 修改JavaScript代码,使其返回一个可被runJavaScript处理的Promise:

将你的代码包装成一个明确返回Promise的函数,并确保这个Promise是脚本的最终返回值。

// 修改后的JavaScript代码
function waitForValue() {
  return new Promise((resolve, reject) => {...});
}

// 关键:返回一个Promise,该Promise最终解析为你想要的值
return (async () => {
  try {
    const val = await waitForValue();
    return val; // 这个val将成为最终Promise的解析值
  } catch (e) {
    console.error(e);
    throw e; // 或者返回一个错误标识,取决于你的错误处理逻辑
  }
})();

2. 在ArkTS中,runJavaScript的返回值将是一个Promise,你需要对其进行链式处理:

this.webviewController.runJavaScript(modifiedCode)
  .then((jsPromise: Promise<Object>) => {
    // runJavaScript返回的是JS端的Promise对象
    return jsPromise; // 将其返回,进行下一级then处理
  })
  .then((resolvedValue: Object) => {
    // 这里得到的才是异步JS代码中await waitForValue()最终解析出来的val
    console.log('最终结果:', resolvedValue);
  })
  .catch((error: Error) => {
    console.error('执行失败:', error);
  });

原理说明:

  • runJavaScript 执行脚本,并捕获脚本最后求值的结果。
  • 如果你的脚本最终求值结果是一个Promise,runJavaScript返回的Promise(ArkTS端)会解析为这个JavaScript Promise对象。
  • 你需要再次调用.then来订阅这个JavaScript Promise的解析结果,从而获取到内部异步操作(waitForValue())的实际返回值。

简洁写法:

你也可以将两步合并,因为runJavaScript返回的Promise解析后就是JS端的Promise。

this.webviewController.runJavaScript(modifiedCode)
  .then((jsPromise: Promise<Object>) => jsPromise)
  .then((finalValue: Object) => {
    console.log('获取到的值:', finalValue);
  });

确保你的JavaScript代码字符串 (modifiedCode) 最终是一个返回Promise的表达式或语句。这样就能正确获取到异步操作的结果,而不是null

回到顶部