JS脚本加载后执行相应回调函数的操作方法


Posted in Javascript onFebruary 28, 2018

项目中经常会遇到这样的问题:当某个 js 脚本加载完成后再执行相应任务,但很多朋友可能并不知道怎么判断我们要加载的 js 文件是否加载完成,如果没有加载完成我们就调用 js 文件里面的函数是不会成功的。本文主要讲解怎么在成功加载 js 文件后再执行相应回调任务。

基本思路

我们可以动态的创建 <script> 元素,然后通过更改它的 src 属性来加载脚本,但是怎么知道这个脚本文件加载完成了呢?因为有些函数需要在脚本加载完成才能调用。IE 浏览器中可以使用 <script> 元素的 onreadystatechange 来监控加载状态的改变,并通过判断它的 readyState 是 loaded 或 complete 来判断脚本是否加载完成。而非 IE 浏览器可以使用 onload 来直接判断脚本是否加载完成。

动态脚本简单示例

一个 简单 的实现过程如下:

// IE下:
var HEAD = document.getElementsByTagName('head')[0] || document.documentElement
var src = 'http://xxxxxx.com'
var script = document.createElement('script')
script.setAttribute('type','text/javascript')
script.onreadystatechange = function() {
 if(this.readyState === 'loaded' || this.readyState === 'complete') {
  console.log('加载成功!')
 }
}
script.setAttribute('src', src)
HEAD.appendChild(script)
// Chrome等现代浏览器:
var HEAD = document.getElementsByTagName('head')[0] || document.documentElement;
var src = 'http://xxxxxx.com'
var script = document.createElement('script')
script.setAttribute('type','text/javascript')
script.onload = function() {
 console.log('加载成功!')
}
script.setAttribute('src', src)
HEAD.appendChild(script)

原理很简单,根据这两个简单的原理,我们进行一些修改,我把改成了两个函数,分别是 串行加载 和 并行加载 。

串行和并行动态脚本

当传一个包含多个JS文件路径的数组时,串行加载函数从第一个脚本文件加载开始,每加载成功一个便开始加载下一个脚本文件,全部加载完成后执行回调函数。而并行加载是一开始便加载全部的脚本文件,也就是他们从同一点开始加载,当全部加载完成后,执行回调函数。

/** 
 * 串行加载指定的脚本
 * 串行加载[异步]逐个加载,每个加载完成后加载下一个
 * 全部加载完成后执行回调
 * @param {Array|String} scripts 指定要加载的脚本
 * @param {Function} callback 成功后回调的函数
 * @return {Array} 所有生成的脚本元素对象数组
 */
function seriesLoadScripts(scripts, callback) {
 if(typeof(scripts) !== 'object') {
  var scripts = [scripts];
 }
 var HEAD = document.getElementsByTagName('head')[0] || document.documentElement;
 var s = [];
 var last = scripts.length - 1;
 //递归
 var recursiveLoad = function(i) {
  s[i] = document.createElement('script');
  s[i].setAttribute('type','text/javascript');
  // Attach handlers for all browsers
  // 异步
  s[i].onload = s[i].onreadystatechange = function() {
   if(!/*@cc_on!@*/0 || this.readyState === 'loaded' || this.readyState === 'complete') {
    this.onload = this.onreadystatechange = null; 
    this.parentNode.removeChild(this);
    if(i !== last) {
     recursiveLoad(i + 1);
    } else if (typeof(callback) === 'function') {
     callback()
    };
   }
  }
  // 同步
  s[i].setAttribute('src', scripts[i]);
  HEAD.appendChild(s[i]);
 };
 recursiveLoad(0);
}
/**
 * 并行加载指定的脚本
 * 并行加载[同步]同时加载,不管上个是否加载完成,直接加载全部
 * 全部加载完成后执行回调
 * @param {Array|String} scripts 指定要加载的脚本
 * @param {Function} callback 成功后回调的函数
 * @return {Array} 所有生成的脚本元素对象数组
 */ 
function parallelLoadScripts(scripts, callback) {
 if(typeof(scripts) !== 'object') {
  var scripts = [scripts];
 }
 var HEAD = document.getElementsByTagName('head')[0] || document.documentElement;
 var s = [];
 var loaded = 0;
 for(var i = 0; i < scripts.length; i++) {
  s[i] = document.createElement('script');
  s[i].setAttribute('type','text/javascript');
  // Attach handlers for all browsers
  // 异步
  s[i].onload = s[i].onreadystatechange = function() {
   if(!/*@cc_on!@*/0 || this.readyState === 'loaded' || this.readyState === 'complete') {
    loaded++;
    this.onload = this.onreadystatechange = null;
    this.parentNode.removeChild(this);
    if(loaded === scripts.length && typeof(callback) === 'function') callback();
   }
  };
  // 同步
  s[i].setAttribute('src',scripts[i]);
  HEAD.appendChild(s[i]);
 }
}

在这里是把 <script> 标签动态的插入到页面中的 <head> 标签内部,并且加载完成后标签元素会被自动移除。

使用方法

这里声明了一个数组变量,里面包含了两个远程的JS文件地址(当然 <script> 标签调用脚本是支持跨域的):

var scripts = [ 
 "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",
 "http://wellstyled.com/files/jquery.debug/jquery.debug.js"
];
// 这两个文件分别是 jQuery 1.4.的库文件和 jQuery Debug 插件
// 然后你可以使用下面的方法调用并在成功后执行回调了。
parallelLoadScripts(scripts, function() { 
 /*
 debug = new $.debug({ 
  posTo : { x:'right', y:'bottom' },
  width: '480px',
  height: '50%',
  itemDivider : '<hr>',
  listDOM : 'all'
 });
 */
 console.log('脚本加载完成啦');
});

总结

以上所述是小编给大家介绍的JS脚本加载后执行相应回调函数操作方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Javascript 写的简单进度条控件
Jan 22 Javascript
javascript中的关于类型转换的性能优化
Dec 14 Javascript
jquery键盘事件介绍
Jan 31 Javascript
读jQuery之一(对象的组成)
Jun 11 Javascript
node.js chat程序如何实现Ajax long-polling长链接刷新模式
Mar 13 Javascript
EasyUI 中 MenuButton 的使用方法
Jul 14 Javascript
js使用for循环查询数组中是否存在某个值
Aug 12 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
Nov 25 Javascript
JS简单实现移动端日历功能示例
Dec 28 Javascript
Base64(二进制)图片编码解析及在各种浏览器的兼容性处理
Feb 09 Javascript
BootStrap 表单控件之单选按钮水平排列
May 23 Javascript
微信小程序激励式视频广告组件使用详解
Dec 06 Javascript
vue+webpack 打包文件 404 页面空白的解决方法
Feb 28 #Javascript
webpack项目调试以及独立打包配置文件的方法
Feb 28 #Javascript
vue-cli+webpack项目 修改项目名称的方法
Feb 28 #Javascript
vue 组件 全局注册和局部注册的实现
Feb 28 #Javascript
vue 自定义全局方法,在组件里面的使用介绍
Feb 28 #Javascript
Vue2.0子同级组件之间数据交互方法
Feb 28 #Javascript
bootstrap table支持高度百分比的实例代码
Feb 28 #Javascript
You might like
YII视图整合kindeditor扩展的方法
2016/07/13 PHP
(function(){})()的用法与优点
2007/03/11 Javascript
javascript 节点遍历函数
2010/03/28 Javascript
JavaScript中String和StringBuffer的速度之争
2010/04/01 Javascript
JavaScript Distilled 基础知识与函数
2010/04/07 Javascript
jQuery EasyUI API 中文文档 - ProgressBar 进度条
2011/09/29 Javascript
JavaScript中this的使用详解
2013/11/08 Javascript
JavaScript导出Excel实例详解
2014/11/25 Javascript
js实现带关闭按钮始终显示在网页最底部工具条的方法
2015/03/02 Javascript
AngularJS学习笔记之基本指令(init、repeat)
2015/06/16 Javascript
javascript实现的简单计时器
2015/07/19 Javascript
JS+CSS实现表格高亮的方法
2015/08/05 Javascript
Vue.js -- 过滤器使用总结
2017/02/18 Javascript
javascript实现下雨效果
2017/03/27 Javascript
详解vue2.0 transition 多个元素嵌套使用过渡
2017/06/19 Javascript
vue实现记事本功能
2019/06/26 Javascript
Node.js安装详细步骤教程(Windows版)详解
2019/09/01 Javascript
vue 判断页面是首次进入还是再次刷新的实例
2020/11/05 Javascript
js实现简易点击切换显示或隐藏
2020/11/29 Javascript
[06:43]2018DOTA2国际邀请赛寻真——VGJ.Thunder
2018/08/11 DOTA
Python用于学习重要算法的模块pygorithm实例浅析
2018/08/16 Python
python将dict中的unicode打印成中文实例
2020/05/11 Python
python FTP编程基础入门
2021/02/27 Python
世界第一冲浪品牌:O’Neill
2016/08/30 全球购物
澳大利亚最超值的自行车之家:Reid Cycles
2019/03/24 全球购物
牧马人澳大利亚官网:Wrangler澳大利亚
2019/10/08 全球购物
编写类String的构造函数、析构函数和赋值函数
2012/05/29 面试题
个人自我鉴定
2013/11/07 职场文书
企业优秀员工事迹材料
2014/05/28 职场文书
环境科学专业求职信
2014/08/04 职场文书
家庭经济困难证明
2015/06/23 职场文书
员工考勤管理制度
2015/08/06 职场文书
《我们的民族小学》教学反思
2016/02/19 职场文书
2016年领导干部廉政承诺书
2016/03/24 职场文书
PHP基本语法
2021/03/31 PHP
springboot应用服务启动事件的监听实现
2022/04/06 Java/Android