Flutter插件中加载Emscripten生成的JS库时遇到异常
解决Flutter Web插件中动态加载Csound脚本的顺序问题
我之前处理过类似的Flutter Web插件脚本加载问题,给你几个针对性的解决方案和思路:
1. 手动控制脚本加载顺序,避免异步冲突
你当前的代码是同时添加两个脚本,即使加了defer,动态脚本的加载顺序也可能因为文件大小、网络速度等因素出现偏差。最好的方式是等CsoundObj.js完全加载并初始化后,再加载CsoundDart.js,可以通过监听onLoad事件实现:
// 先加载CsoundObj.js final csoundObjScript = html.ScriptElement() ..src = "assets/packages/csounddart/assets/CsoundObj.js" ..type = "text/javascript"; // 监听CsoundObj.js加载完成事件 csoundObjScript.onLoad.listen((_) { // 加载完成后再添加CsoundDart.js final csoundDartScript = html.ScriptElement() ..src = "assets/packages/csounddart/assets/CsoundDart.js" ..type = "text/javascript"; html.document.body?.append(csoundDartScript); }); html.document.body?.append(csoundObjScript);
这种方式能确保CsoundDart.js运行时,CsoundObj已经存在于全局作用域中。
2. 用Flutter插件官方的脚本加载器
Flutter Web插件提供了专门的registrar.loader来处理脚本加载,它能更好地适配插件上下文,并且天然支持异步顺序加载:
import 'package:flutter_web_plugins/flutter_web_plugins.dart'; void registerCsoundDartPlugin(Registrar registrar) { // 先加载CsoundObj.js,等待加载完成 registrar.loader.loadScript(Uri.parse('packages/csounddart/assets/CsoundObj.js')).then((_) { // 再加载CsoundDart.js registrar.loader.loadScript(Uri.parse('packages/csounddart/assets/CsoundDart.js')).then((_) { // 在这里初始化你的插件核心逻辑 }); }); }
这种方式比手动操作DOM更符合Flutter插件的规范,也能避免很多作用域或加载时机的问题。
3. 考虑Emscripten脚本的特殊性
CsoundObj.js是Emscripten生成的,这类脚本通常不会在加载完成后立刻暴露全局对象,而是要等运行时初始化完成。你可以检查脚本中是否有Module.onRuntimeInitialized这类回调(Emscripten的标准回调),如果有的话,需要等这个回调触发后再加载CsoundDart.js:
csoundObjScript.onLoad.listen((_) { // 等待Emscripten模块初始化完成 if (html.window.hasProperty('Module')) { final module = html.window['Module']; module['onRuntimeInitialized'] = () { // 此时CsoundObj应该已成功注册到全局 final csoundDartScript = html.ScriptElement() ..src = "assets/packages/csounddart/assets/CsoundDart.js" ..type = "text/javascript"; html.document.body?.append(csoundDartScript); }; } });
4. 验证Assets路径和配置
最后别忘了检查pubspec.yaml中的Assets配置是否正确,确保两个脚本都被正确打包:
flutter: assets: - packages/csounddart/assets/CsoundObj.js - packages/csounddart/assets/CsoundDart.js
同时可以打开浏览器开发者工具的Network标签,确认两个脚本的HTTP状态码是200,没有加载失败的情况。
内容的提问来源于stack exchange,提问作者Philiste
相关产品推荐
相关产品推荐

