WordPress中依赖脚本加载顺序混乱时,如何基于Promise或jQuery Deferred实现可靠的函数就绪检测?
解决脚本加载顺序混乱下的函数依赖问题
作为常年跟WordPress各种“优化”插件斗智斗勇的开发者,我太懂你这种崩溃感了——明明按顺序写的脚本,被插件一顿乱排,依赖直接炸锅,Promise又像《信条》一样绕得头大?别慌,我给你捋清楚两个靠谱的方案,不管加载顺序怎么乱都能搞定。
核心思路
你之前的问题在于:当依赖脚本后加载时,用来标记状态的变量还没定义,直接报错。我们需要一个全局的状态容器,不管哪个脚本先加载,都能先初始化这个容器,后加载的脚本只需要监听容器的状态变化即可,完全不依赖加载顺序。
方案一:原生Promise实现(无需jQuery)
这个方案用原生JS就能搞定,不用额外依赖:
a.js(包含Function A的文件)
// 先检查全局有没有这个Promise容器,没有就创建一个Pending状态的Promise window.isMyFunctionReady = window.isMyFunctionReady || new Promise((resolve) => { // 把resolve方法挂到全局,方便后续触发 window.resolveMyFunction = resolve; }); // 定义你的Function A function FunctionA() { // 你的函数逻辑 console.log('Function A 已加载完成'); } // 当Function A准备好后,触发resolve,告诉依赖它的脚本可以执行了 window.resolveMyFunction();
b.js(包含Function B的文件)
// 同样先确保全局有这个Promise容器,防止a.js还没加载 window.isMyFunctionReady = window.isMyFunctionReady || new Promise((resolve) => { window.resolveMyFunction = resolve; }); // 等待Function A准备好,再执行Function B的逻辑 window.isMyFunctionReady.then(() => { // 现在可以安全调用Function A了 FunctionA(); console.log('Yes, my function is ready, I can now use it.'); }).catch(() => { console.log('Couldnt load my function'); });
为什么这个方案能行?
- 如果a.js先加载:它会创建Promise容器,定义
resolveMyFunction,执行完Function A后触发resolve,此时b.js加载后,then里的逻辑会立刻执行。 - 如果b.js先加载:它会创建一个Pending状态的Promise,
then会处于等待状态。当a.js加载时,会复用这个全局的Promise,触发resolveMyFunction()后,b.js里的等待逻辑就会被执行。
方案二:jQuery Deferred实现(适合已用jQuery的项目)
如果你对jQuery更熟悉,Deferred的逻辑和Promise一致,只是API更贴合jQuery的使用习惯:
a.js(包含Function A的文件)
// 先检查全局有没有Deferred容器,没有就创建 window.myFunctionDeferred = window.myFunctionDeferred || $.Deferred(); // 定义你的Function A function FunctionA() { console.log('Function A 已加载完成'); } // 当Function A准备好,标记Deferred为完成状态 window.myFunctionDeferred.resolve();
b.js(包含Function B的文件)
// 同样先确保全局有Deferred容器 window.myFunctionDeferred = window.myFunctionDeferred || $.Deferred(); // 等待Deferred完成后执行逻辑 window.myFunctionDeferred.done(() => { // 安全调用Function A FunctionA(); console.log('Yes, my function is ready, I can now use it.'); }).fail(() => { console.log('Couldnt load my function'); });
逻辑解释
Deferred的resolve()对应Promise的resolve,done()对应Promise的then(),不管哪个脚本先加载,全局的Deferred容器都会被正确初始化,后加载的脚本只要监听它的状态变化就行,完美规避加载顺序问题。
小提醒
为了避免和其他主题/插件的全局变量冲突,建议给你的状态容器加个独特前缀,比如myTheme_isMyFunctionReady或者myPlugin_deferred,这样更安全。
内容的提问来源于stack exchange,提问作者Aleksandar
相关产品推荐
相关产品推荐

