关于javascript:让我的用户脚本等待加载其他脚本

Make my userscript wait for other scripts to load

[编辑:我将用一个演示问题的简化示例替换原始的、令人困惑的问题。]

背景

我正在尝试编写一个在chrome中运行的用户脚本。这个脚本需要调用一个在用户脚本之外的javascript函数AlertMe()--这个函数是页面的一部分,包含在服务器端动态生成的变量,因此不可能在我的用户脚本中重新编写这个函数。

代码

页面上的脚本(访问页面):

1
2
3
4
5
6
7
<script type="text/javascript">
    function AlertMe()
    {
        alert("Function AlertMe was called!");
        // then do stuff with strings that were dynamically generated
        // on the server so that I can't easily rewrite this into the userscript
    }

我的用户脚本(在chrome中安装):

1
2
3
4
5
6
7
8
9
10
11
12
function tryAlert()
{
    if (typeof AlertMe =="undefined") {
        console.log('AlertMe is undefined.');
        window.setTimeout(tryAlert, 100);
    }
    else {
        AlertMe();
    }
}

tryAlert();

问题

当我试图简单地调用函数时,chrome的控制台告诉我AlertMe is not defined。我认为这是因为我的用户脚本在所有其他脚本加载之前就已经运行了,所以我使用setTimeout等待AlertMe函数被定义。

不幸的是,如果安装该脚本,然后访问该页面,您将看到它将永远输出AlertMe is undefined.,并且从不调用该函数。如果在chrome的控制台中键入typeof AlertMe,它会正确地响应"function",那么为什么我的用户脚本总是认为AlertMe是未定义的?


您总是可以编写一个小函数来检查函数是否被加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function waitForFnc(){
  if(typeof absearch =="undefined"){
    window.setTimeout(waitForFnc,50);
  }
  else{
    runMyFunction();
  }
}

function runMyFunction(){
    var urlParams = window.location.search.substring(1).split('&'),
        username ="",
        hscEmailInput = document.getElementById('userfield6'),
        i = 0;
    if (urlParams !=="") {
        for (i = 0; i < urlParams.length; i++) {
            if (urlParams[i].substr(0,4) ==="USER") {
                username = urlParams[i].replace('USER=', '');
                hscEmailInput.value = username + '@example.com';
                absearch('&PAGESIZE=1');
            }
        }
    }
}

waitForFnc();


这不是时间问题。

您遇到了GreaseMonkey的安全限制,这会阻止您执行页面中的函数。请参阅我对前一个问题的回答,以获得解释和一些安全的解决方法:

用户脚本和greasemonkey:调用网站的javascript函数


如果问题确实是脚本运行得太早,那么解决方案可能是检查并等待DOM准备就绪:依赖于DOM准备好调用函数(而不是window.onload)。

编辑

这样的答案也可能被证明是有用的。