从JS中的另一个脚本获取函数

时间:2009-08-15 12:29:16

标签: javascript scripting

我从书签中加载这个JS代码:

function in_array(a, b)
{
  for (i in b)
    if (b[i] == a)
      return true;
  return false;
}

function include_dom(script_filename) {
    var html_doc = document.getElementsByTagName('head').item(0);
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', script_filename);
    html_doc.appendChild(js);
    return false;
}

var itemname = '';
var currency = '';
var price    = '';

var supported = new Array('www.amazon.com');
var domain = document.domain;

if (in_array(domain, supported))
{
  include_dom('http://localhost/bklts/parse/'+domain+'.js');
  alert(getName());
}
[...]

请注意,'getName()'函数位于http://localhost/bklts/parse/www.amazon.com/js。这段代码只在我点击书签的第二时间起作用(该函数似乎在alert()之后才加载。)

奇怪的是,如果我将代码更改为:

if (in_array(domain, supported))
{
  include_dom('http://localhost/bklts/parse/'+domain+'.js');
  alert('hello there');
  alert(getName());
}

我在第一次点击时获得两个警报,其余的脚本功能。如何在没有虚假警报的情况下首次单击书签时使脚本工作?

谢谢! -Mala

3 个答案:

答案 0 :(得分:2)

添加<脚本>标签通过DHTML使脚本加载异常,这意味着浏览器将开始加载它,但不会等待它运行其余的脚本。

您可以处理标记对象上的事件,以找出加载脚本的时间。这是我使用的一段示例代码似乎在所有浏览器中都能正常工作,虽然我确信这是实现这一目标的更好方法,但我希望这应该指向正确的方向:

不要忘记将标记更改为包含< script>的对象element,fnLoader为加载脚本时调用的函数,fnError为函数,如果加载脚本失败则调用。

请记住,这些函数将在以后调用,因此它们(如tag)必须可用(闭包通常会处理)。

        tag.onload = fnLoader;
    tag.onerror = fnError;
    tag.onreadystatechange = function() {
        if (!window.opera && typeof tag.readyState == "string"){
            /* Disgusting IE fix */
            if (tag.readyState == "complete" || tag.readyState == "loaded") {
                fnLoader();
            } else if (tag.readyState != "loading") {
                fnError();
            };
        } else if (tag.readyState == 4) {
            if (tag.status != 200) {
                fnLoader();
            }
            else {
                fnError();
            };
        };
    });

答案 1 :(得分:0)

听起来外部脚本(http://localhost/bklts/parse/www.amazon.com/js)的加载在加载之前不会阻止执行。简单的超时可能足以让浏览器有机会更新DOM,然后立即排队执行下一个逻辑块:

//...
if (in_array(domain, supported))
{
    include_dom('http://localhost/bklts/parse/'+domain+'.js');
    setTimeout(function() {
        alert(getName());
    }, 0);
}
//...

根据我的经验,如果零对超时量不起作用,那么你就有了真正的竞争条件。延长时间(例如10-100)可能会在某些情况下修复它,但是如果你需要它可以始终工作,你会遇到危险的情况。如果零对你有效,那么它应该是非常可靠的。如果没有,那么您可能需要将更多(全部?)剩余的代码推送到外部脚本中。

答案 2 :(得分:0)

我能开展工作的最佳方式:不要。

因为无论如何我从一个小的装载程序书签中调用JS(它只是将脚本固定到你正在查看的页面上)我修改了bookmarklet以将src指向一个输出JS代码的php脚本, document.domain作为参数。因此,我只使用php来包含外部代码。

希望有人帮助。由于这不是我的问题的答案,我不会将此标记为已接受的答案。如果有人有更好的方法,我很想知道,但我会按原样离开我的代码:

书签:

javascript:(function(){document.body.appendChild(document.createElement('script')).src='http://localhost/bklts/div.php?d='+escape(document.domain);})();

本地主机/ bklts / div.php:

<?php

print("
// JS code
");

$supported = array("www.amazon.com", "www.amazon.co.uk");
$domain = @$_GET['d']
if (in_array($domain, $supported))
    include("parse/$domain.js");

print("
// more JS code
");

?>