Flutter Web中如何从异步JS函数获取回调或返回值至Dart
在Flutter Web中实现JS异步结果返回Dart的解决方案
针对你遇到的JS异步函数结果无法返回至Dart的问题,以下是具体的原因分析和可行方案:
错误原因分析
- 示例1:仅调用JS函数但未处理其返回的Promise,因此无法获取结果。
- 示例2:
js.context.callMethod返回的是JsObject而非原生JS Promise,promiseToFuture无法识别这种对象的then方法,导致报错。 - 示例3:未正确声明JS异步函数的返回类型,Dart无法将返回的JS Promise转换为可await的Future,引发类型错误。
可行实现方案
步骤1:确保JS函数全局可访问
你的JS代码无需大幅修改,只需确保fileOpen函数挂载到全局window对象上(通常在index.html的<script>标签中定义即可):
let fileHandle; async function fileOpen() { try { [fileHandle] = await window.showOpenFilePicker(); const file = await fileHandle.getFile(); if (file) { const parser = new window.AppInfoParser(file); const result = await parser.parse(); return result; } else { return 'File not selected'; } } catch (err) { // 捕获用户取消文件选择等异常 throw err; } }
步骤2:Dart端正确处理JS Promise
使用package:js和js_util库,正确声明JS异步函数并将其Promise转换为Dart Future:
import 'package:js/js.dart'; import 'package:js/js_util.dart'; // 定义JS Promise的Dart映射类,让Dart识别Promise接口 @JS() class Promise<T> { external Promise then(void Function(T result) onSuccess, [Function onError]); } // 声明全局的JS异步函数,返回Promise @JS() external Promise<dynamic> fileOpen(); // 在点击事件或异步方法中调用并获取结果 Future<void> handleFileOpen() async { try { dynamic result = await promiseToFuture(fileOpen()); // 处理返回的结果,比如打印或更新UI print('Received result from JS: $result'); if (result is Map) { print('App icon base64: ${result['icon']}'); } } catch (e) { // 处理异常,比如用户取消文件选择 print('Error occurred: $e'); } }
关键注意点
- 必须用
try-catch包裹异步调用,因为用户取消文件选择器时window.showOpenFilePicker会抛出异常,需要在Dart中捕获。 - 通过
@JS()注解声明的函数必须与全局JS函数名完全一致,确保Dart能正确找到对应的JS函数。 - 使用
promiseToFuture将JS Promise转换为Dart Future,才能用await获取结果。
内容的提问来源于stack exchange,提问作者Patel Pinkal
相关产品推荐
相关产品推荐

