如何确保动态加载的脚本在调用指定函数前完全加载?
解决Angular动态脚本加载与用户操作时序冲突问题
核心思路
通过Promise跟踪脚本加载状态,让按钮点击逻辑等待脚本完全加载(含加载失败场景)后再执行,同时搭配UI层面的禁用控制,从根源避免用户在脚本未就绪时触发操作。
具体实现步骤
1. 组件内维护脚本加载状态变量
在组件类中添加用于跟踪加载状态的Promise和UI控制变量:
import { Component, OnInit, OnDestroy, Renderer2, Inject } from '@angular/core'; import { DOCUMENT } from '@angular/common'; export class HomeComponent implements OnInit, OnDestroy { private script: any; private scriptLoadedPromise: Promise<void>; // 跟踪脚本加载完成状态 public isScriptLoaded = false; // 用于控制按钮禁用状态 constructor( private _renderer2: Renderer2, @Inject(DOCUMENT) private _document: Document ) {}
2. 把脚本加载封装成Promise
修改insertDynamicallyScript方法,将脚本加载过程包装为Promise,确保加载成功/失败时都能触发状态变更:
public insertDynamicallyScript(): void { this.scriptLoadedPromise = new Promise((resolve, reject) => { this.script = this._renderer2.createElement('script'); this.script.type = 'text/javascript'; this.script.src = 'url.here'; this.script.async = false; // 脚本加载成功回调 this.script.onload = () => { console.log('Script loaded'); this.isScriptLoaded = true; resolve(); }; // 脚本加载失败回调,避免Promise一直处于pending状态 this.script.onerror = (error: ErrorEvent) => { console.error('Script load failed:', error); reject(new Error('Required script failed to load')); }; this._renderer2.appendChild(this._document.body, this.script); }); }
3. 修改按钮点击函数,等待脚本加载完成
在userButtonActionFunction中先等待脚本加载Promise完成,再执行业务逻辑:
public async userButtonActionFunction(): Promise<void> { try { // 等待脚本加载完成,加载失败会直接进入catch块 await this.scriptLoadedPromise; if (window['scriptFunction']) { await window['scriptFunction'].doSomething(); } else { console.error('Script loaded but target function not found'); // 这里可添加用户友好提示,比如弹窗告知功能暂时不可用 } } catch (exception) { console.error('Error during script operation:', exception); // 处理脚本加载失败或执行出错的情况,比如显示错误提示 } finally { // 无论成功失败都要执行的逻辑 } }
4. (可选)UI层面禁用按钮
在模板中给按钮绑定禁用状态,直到脚本加载完成才允许点击:
<button (click)="userButtonActionFunction()" [disabled]="!isScriptLoaded" > {{ isScriptLoaded ? '执行操作' : '加载中...' }} </button>
额外注意事项
- 修正原代码语法错误:类成员定义不需要加
this.,比如把this.script: any;改为private script: any;; - 确保
DOCUMENT从@angular/common导入,避免依赖注入报错; - 可添加重复加载判断:插入脚本前先检查
window['scriptFunction']是否已存在,避免重复插入脚本; - 脚本加载失败时要给出明确的用户提示,提升体验。
内容的提问来源于stack exchange,提问作者RonanFelipe
相关产品推荐
相关产品推荐

