我如何在Chrome扩展中使用setTimeout注入jQuery到页面?



我已经建立了一个chrome扩展,其中一个功能是检查页面上的jQuery,如果它不存在,那么将其添加到页面。我从一个旧的扩展重新利用一些代码,而它的工作如预期的(99%的时间),我想了解setTimeout在这种情况下的使用。

在大多数情况下,setTimeout(addjQuery)addjQuery()似乎都可以正常工作。下面是代码,就像我说的,它几乎总是有效的。

更新问一个特定的问题…我使用下面的语法将jquery和myLibrary注入页面。正如您在onMyLibraryLoaded函数中看到的那样,我试图使用jQuery将模糊事件附加到所有输入。这几乎总是有效的……为什么它有时会抛出jQuery未定义的错误?我唯一的解释是,偶尔myLibrary加载速度比jquery快,并在jquery准备好之前触发?对吗?我该如何解决这个问题?等待吗?

if (!window['jQuery']) {  
setTimeout(addjQuery);    
}
if (!window['myLibrary']) {  
setTimeout(addMyLibrary);    
}
function addjQuery() {
const script = document.createElement('script');
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js';
script.onload = onjQueryLoaded;
document.body.appendChild(script);        
}
function addMyLibrary() {
const script = document.createElement('script');
script.src = 'https://jrags/myLibrary.min.js';
script.onload = onMyLibraryLoaded;
document.body.appendChild(script);        
}

function onMyLibraryLoaded(){
$(document).on("blur", "#someInput", function(){
console.log("Input blurred");
})
}
function onjQueryLoaded(){
console.log('jquery loaded sucessfully')
}

通过互联网获取这两个库都需要时间。并且每次运行时可能会有不同的时间。通过延迟创建脚本元素的调用,您已经在下一个事件周期中启动了加载,但这与您所观察到的情况无关。需要说明的是,您所写的setTimeout调用是不必要的。

如果您查看浏览器的开发人员工具以查看发生了哪些网络请求以及它们完成的顺序,您将发现在失败的情况下,https://jrags/myLibrary.min.js库将在之前加载。加载jQuery库。但是您已经在处理程序中使用了jQuery函数来加载库(特别是script.onload = onMyLibraryLoaded;onMyLibraryLoaded调用$(document),这需要加载jQuery。)

有几种方法可以解决这个问题。一种方法是延迟加载脚本,直到加载了jQuery。但实际上,最好是尽快开始工作。因此,一个不同的,更有效的方法是推迟模糊#someInput,直到jQuery也加载。

我最好的建议是使用一个Promise来加载每个库,并在两个Promise都解决后执行blur。

function addLibrary(src) {
return new Promise(resolve => {
const script = document.createElement('script');
script.src = src;
script.onload = resolve;
document.body.appendChild(script);        
})
}
let p1 = addLibrary('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js')
.then(() => console.log('jQuery loaded'));
let p2 = addLibrary('https://jrags/myLibrary.min.js')
.then(() => console.log('myLibrary loaded'));
Promise.all([p1, p2]).then(() => {
$(document).on("blur", "#someInput", function(){
console.log("Input blurred");
})
});

或与await:

let p1 = addLibrary('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js');
let p2 = addLibrary('https://jrags/myLibrary.min.js');
await p1;
await p2;
$(document).on("blur", "#someInput", function(){
console.log("Input blurred");
})

最新更新