草庐IT

javascript - 动态脚本加载同步

coder 2024-05-16 原文

我有一个脚本知道加载包含 javascript 类的动态脚本。 我正在使用以下代码加载类脚本:

var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "myscript.js";
head.appendChild(script);

然后我尝试使用 eval 创建新类:

var classObj = eval(" new MyClass()" );

问题是 eval 的代码是在脚本加载到内存之前执行的,我得到一个错误,指出 MyClass 未定义。

有没有办法同步这些事件?在开始从中分配类之前,我需要确保脚本已完全加载到内存中。

最佳答案

您需要将事件处理程序附加到 onload 方法,在符合 Web 标准的浏览器中,或 onreadystatechange,检查 script.readyState 属性是否等于“加载”或“完成”,在 Internet Explorer 中。

在您收到脚本已加载的通知之前,您可能正在尝试访问尚未声明或创建的对象、函数和属性。

这是从模块 bezen.dom.js 中提取的示例函数在我的 Javascript library, bezen.org :

var appendScript = function(parent, scriptElt, listener) {
    // append a script element as last child in parent and configure 
    // provided listener function for the script load event
    //
    // params:
    //   parent - (DOM element) (!nil) the parent node to append the script to
    //   scriptElt - (DOM element) (!nil) a new script element 
    //   listener - (function) (!nil) listener function for script load event
    //
    // Notes:
    //   - in IE, the load event is simulated by setting an intermediate 
    //     listener to onreadystate which filters events and fires the
    //     callback just once when the state is "loaded" or "complete"
    //
    //   - Opera supports both readyState and onload, but does not behave in
    //     the exact same way as IE for readyState, e.g. "loaded" may be
    //     reached before the script runs.

    var safelistener = catchError(listener,'script.onload');

    // Opera has readyState too, but does not behave in a consistent way
    if (scriptElt.readyState && scriptElt.onload!==null) {
      // IE only (onload===undefined) not Opera (onload===null)
      scriptElt.onreadystatechange = function() {
        if ( scriptElt.readyState === "loaded" || 
             scriptElt.readyState === "complete" ) {
          // Avoid memory leaks (and duplicate call to callback) in IE
          scriptElt.onreadystatechange = null;
          safelistener();
        }
      };
    } else {
      // other browsers (DOM Level 0)
      scriptElt.onload = safelistener;
    }
    parent.appendChild( scriptElt );
};

为了使其适应您的需要,您可以替换对 catchError 的调用,它包装了监听器以捕获和记录错误,并使用修改后的函数:

var appendScript = function(parent, scriptElt, listener) {
    // append a script element as last child in parent and configure 
    // provided listener function for the script load event
    //
    // params:
    //   parent - (DOM element) (!nil) the parent node to append the script to
    //   scriptElt - (DOM element) (!nil) a new script element 
    //   listener - (function) (!nil) listener function for script load event
    //
    // Notes:
    //   - in IE, the load event is simulated by setting an intermediate 
    //     listener to onreadystate which filters events and fires the
    //     callback just once when the state is "loaded" or "complete"
    //
    //   - Opera supports both readyState and onload, but does not behave in
    //     the exact same way as IE for readyState, e.g. "loaded" may be
    //     reached before the script runs.

    var safelistener = function(){
      try {
        listener();
      } catch(e) {
        // do something with the error
      }
    };

    // Opera has readyState too, but does not behave in a consistent way
    if (scriptElt.readyState && scriptElt.onload!==null) {
      // IE only (onload===undefined) not Opera (onload===null)
      scriptElt.onreadystatechange = function() {
        if ( scriptElt.readyState === "loaded" || 
             scriptElt.readyState === "complete" ) {
          // Avoid memory leaks (and duplicate call to callback) in IE
          scriptElt.onreadystatechange = null;
          safelistener();
        }
      };
    } else {
      // other browsers (DOM Level 0)
      scriptElt.onload = safelistener;
    }
    parent.appendChild( scriptElt );
};

关于javascript - 动态脚本加载同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/774752/

有关javascript - 动态脚本加载同步的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  3. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  4. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  5. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  6. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  7. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  8. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  9. ruby - 确定 ruby​​ 脚本是否已经在运行 - 2

    有没有一种简单的方法可以判断ruby​​脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免

  10. ruby - 在 Ruby 中动态创建数组 - 2

    有没有办法在Ruby中动态创建数组?例如,假设我想遍历用户输入的书籍数组:books=gets.chomp用户输入:"TheGreatGatsby,CrimeandPunishment,Dracula,Fahrenheit451,PrideandPrejudice,SenseandSensibility,Slaughterhouse-Five,TheAdventuresofHuckleberryFinn"我把它变成一个数组:books_array=books.split(",")现在,对于用户输入的每一本书,我想用Ruby创建一个数组。伪代码来做到这一点:x=0books_array.

随机推荐