HarmonyOS鸿蒙Next中在webview异步调用方法
HarmonyOS鸿蒙Next中在webview异步调用方法 现在希望在 webview 中调用一个鸿蒙注入到 window 上的方法,按照文档说明:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/web-in-page-app-function-invoking#promise%E5%9C%BA%E6%99%AF
应该是可以实现的,但是实际测试中总是返回一个空对象,并没有返回 promise 对象。
更多关于HarmonyOS鸿蒙Next中在webview异步调用方法的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者你好,
根据提供的链接,测试是可以正常返回结果的。实际测试中总是返回一个空对象,并没有返回 promise 对象具体是指在哪一侧返回的结果呢,是打印的空对象还是调试获取到的是空对象呢。是否可以提供demo呢。
本地测试代码:
// xxx.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
class TestClass {
constructor() {
}
test(): Promise<string> {
let p: Promise<string> = new Promise((resolve, reject) => {
setTimeout(() => {
console.info('执行完成');
resolve('success');
}, 5000);
});
return p;
}
toString(param: string): void {
console.info(' ' + param);
}
}
@Entry
@Component
struct Index {
webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: TestClass = new TestClass();
build() {
Column() {
Web({ src: $rawfile('test4.html'), controller: this.webviewController })
.javaScriptProxy({
object: this.testObj,
name: 'testObjName',
methodList: ['test', 'toString'],
controller: this.webviewController,
});
};
}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>
function callArkTS() {
testObjName.test().then((param)=>{testObjName.toString(param)}).catch((param)=>{testObjName.toString(param)})
}
</script>
</body>
</html>
更多关于HarmonyOS鸿蒙Next中在webview异步调用方法的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
关注,顶帖
小伙伴你好,可以通过 javaScriptProxy 注册原生方法,当原生方法返回 Promise 时,Web 页面可以使用 .then() 或 async/await 来处理异步结果。
详细说明
方案一:原生方法返回 Promise
方案说明:在原生侧定义返回 Promise 的方法,通过 javaScriptProxy 注册给 Web 页面调用。Web 页面可以通过 Promise 的 .then()、.catch() 或 async/await 语法来处理异步结果。这种方式适合需要异步操作的原生能力调用,如文件读写、网络请求、权限检查等。
实现步骤:
1. 定义返回 Promise 的原生桥接类
// Index.ets
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
/**
* 定义供前端调用的原生对象类
* 支持返回 Promise 的异步方法
*/
class NativeBridge {
/**
* 异步获取设备信息
* @returns Promise<string> 设备信息字符串
*/
getDeviceInfoAsync(): Promise<string> {
return new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => {
try {
const deviceInfo = 'HarmonyOS Device';
resolve(deviceInfo);
} catch (error) {
reject(error);
}
}, 1000);
});
}
/**
* 异步检查权限
* @param permission 权限名称
* @returns Promise<boolean> 是否有权限
*/
checkPermissionAsync(permission: string): Promise<boolean> {
return new Promise((resolve, reject) => {
// 模拟权限检查异步操作
setTimeout(() => {
try {
// 实际项目中应调用权限检查 API
const hasPermission = true;
resolve(hasPermission);
} catch (error) {
reject(error);
}
}, 500);
});
}
/**
* 异步读取文件
* @param filePath 文件路径
* @returns Promise<string> 文件内容
*/
readFileAsync(filePath: string): Promise<string> {
return new Promise((resolve, reject) => {
// 模拟文件读取异步操作
setTimeout(() => {
try {
// 实际项目中应调用文件系统 API
const content = 'File content';
resolve(content);
} catch (error) {
reject(error);
}
}, 2000);
});
}
}
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
// 创建原生桥接对象
nativeBridge: NativeBridge = new NativeBridge();
aboutToAppear() {
// 注册原生对象供前端调用
this.controller.registerJavaScriptProxy({
object: this.nativeBridge,
name: 'nativeBridge',
methodList: ['getDeviceInfoAsync', 'checkPermissionAsync', 'readFileAsync'],
controller: this.controller
});
}
build() {
Column() {
Web({ src: $rawfile('index.html'), controller: this.controller })
.width('100%')
.height('100%')
}
}
}
2. Web 页面调用 Promise 方法
在 Web 页面中,可以通过多种方式调用返回 Promise 的原生方法:
方式一:使用 .then() 和 .catch()
// 前端 JavaScript 代码
// 调用异步获取设备信息
nativeBridge.getDeviceInfoAsync()
.then((deviceInfo) => {
console.log('设备信息:', deviceInfo);
// 处理成功结果
})
.catch((error) => {
console.error('获取设备信息失败:', error);
// 处理错误
});
// 调用异步权限检查
nativeBridge.checkPermissionAsync('camera')
.then((hasPermission) => {
if (hasPermission) {
console.log('有权限');
} else {
console.log('无权限');
}
})
.catch((error) => {
console.error('权限检查失败:', error);
});
方式二:使用 async/await(推荐)
// 前端 JavaScript 代码
async function handleDeviceInfo() {
try {
const deviceInfo = await nativeBridge.getDeviceInfoAsync();
console.log('设备信息:', deviceInfo);
// 处理成功结果
} catch (error) {
console.error('获取设备信息失败:', error);
// 处理错误
}
}
async function handlePermissionCheck() {
try {
const hasPermission = await nativeBridge.checkPermissionAsync('camera');
if (hasPermission) {
console.log('有权限');
} else {
console.log('无权限');
}
} catch (error) {
console.error('权限检查失败:', error);
}
}
// 调用异步函数
handleDeviceInfo();
handlePermissionCheck();
方式三:链式调用多个 Promise
// 前端 JavaScript 代码
// 顺序执行多个异步操作
nativeBridge.checkPermissionAsync('camera')
.then((hasPermission) => {
if (hasPermission) {
return nativeBridge.getDeviceInfoAsync();
} else {
throw new Error('无权限');
}
})
.then((deviceInfo) => {
console.log('设备信息:', deviceInfo);
return nativeBridge.readFileAsync('/path/to/file');
})
.then((fileContent) => {
console.log('文件内容:', fileContent);
})
.catch((error) => {
console.error('操作失败:', error);
});
方式四:并行执行多个 Promise
// 前端 JavaScript 代码
// 使用 Promise.all 并行执行多个异步操作
Promise.all([
nativeBridge.getDeviceInfoAsync(),
nativeBridge.checkPermissionAsync('camera'),
nativeBridge.readFileAsync('/path/to/file')
])
.then((results) => {
const [deviceInfo, hasPermission, fileContent] = results;
console.log('设备信息:', deviceInfo);
console.log('权限状态:', hasPermission);
console.log('文件内容:', fileContent);
})
.catch((error) => {
console.error('操作失败:', error);
});
关键 API 说明:
- javaScriptProxy:注册应用侧对象供前端调用
- registerJavaScriptProxy:动态注册 JavaScript 代理对象
方案二:使用回调函数处理异步结果
方案说明:如果不想使用 Promise,也可以通过回调函数的方式处理异步结果。原生方法接收回调函数作为参数,在异步操作完成后调用回调函数返回结果。
代码示例:
// Index.ets
import { webview } from '@kit.ArkWeb';
/**
* 使用回调函数处理异步结果的原生桥接类
*/
class NativeBridgeWithCallback {
/**
* 异步获取设备信息(回调方式)
* @param callback 回调函数,接收设备信息字符串
*/
getDeviceInfoWithCallback(callback: (deviceInfo: string) => void): void {
// 模拟异步操作
setTimeout(() => {
const deviceInfo = 'HarmonyOS Device';
callback(deviceInfo);
}, 1000);
}
/**
* 异步操作(支持成功和失败回调)
* @param onSuccess 成功回调
* @param onError 失败回调
*/
asyncOperationWithCallbacks(
onSuccess: (result: string) => void,
onError: (error: string) => void
): void {
setTimeout(() => {
try {
const result = '操作成功';
onSuccess(result);
} catch (error) {
onError('操作失败');
}
}, 1000);
}
}
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
nativeBridge: NativeBridgeWithCallback = new NativeBridgeWithCallback();
aboutToAppear() {
this.controller.registerJavaScriptProxy({
object: this.nativeBridge,
name: 'nativeBridge',
methodList: ['getDeviceInfoWithCallback', 'asyncOperationWithCallbacks'],
controller: this.controller
});
}
build() {
Column() {
Web({ src: $rawfile('index.html'), controller: this.controller })
.width('100%')
.height('100%')
}
}
}
前端调用示例:
// 前端 JavaScript 代码
// 使用回调函数
nativeBridge.getDeviceInfoWithCallback((deviceInfo) => {
console.log('设备信息:', deviceInfo);
});
// 使用成功和失败回调
nativeBridge.asyncOperationWithCallbacks(
(result) => {
console.log('操作成功:', result);
},
(error) => {
console.error('操作失败:', error);
}
);
参考文档
- Web 页面调用应用侧函数:官方文档中关于 Promise 场景的详细说明
- javaScriptProxy:Web 组件 JavaScript 代理 API 参考
- registerJavaScriptProxy:动态注册 JavaScript 代理对象 API 参考
- Web 组件概述:Web 组件使用指南
我看你找的这个官方文档写的很详细,还有Demo可以参考,应该没问题的。
要不你多贴点代码,帮你分析分析
在HarmonyOS Next中,Web组件通过postMessage与前端页面进行异步通信。前端通过window.chrome.webview.postMessage发送消息,鸿蒙应用侧在Web组件上监听onMessageEvent事件接收并处理。应用侧也可通过postMessage向Web页面发送数据,前端通过window.onmessage监听。这是一种基于消息的事件驱动异步交互机制。
在HarmonyOS Next的WebView中异步调用注入方法时,如果返回空对象而非Promise,通常是由于注入方法未正确返回Promise或通信机制存在配置问题。
请按以下步骤排查:
-
确认注入方法正确性:确保ArkTS侧通过
registerJavaScriptProxy()注入的方法返回一个Promise对象。例如:// ArkTS侧 webview.registerJavaScriptProxy({ myAsyncMethod: () => { return new Promise((resolve) => { setTimeout(() => resolve("data"), 1000); }); } }, "namespace"); -
检查Web侧调用方式:在Web页面中通过
window.namespace.myAsyncMethod()调用后,需使用.then()或await处理Promise:// Web侧 window.namespace.myAsyncMethod().then(data => console.log(data)); -
验证通信开关:确保WebView已启用JavaScript调用ArkTS的能力:
webviewController.enableJavaScriptProxy(true); -
排查Promise链断裂:若注入方法涉及异步操作(如网络请求),需确保Promise链完整,无未捕获的异常。
若问题仍存在,可检查WebView初始化时机,确保注入在页面加载前完成(如onPageBegin回调中注入),并确认HarmonyOS SDK版本已支持Promise类型返回。


