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 相关文章推荐
以JSON形式将JS中Array对象数组传至后台的方法
Jan 06 Javascript
JavaScript函数定义的常见注意事项小结
Sep 16 Javascript
clipboard.js无需Flash无需依赖任何JS库实现文本复制与剪切
Oct 10 Javascript
javascript如何实现暂停功能
Nov 06 Javascript
request请求获取参数的实现方法(post和get两种方式)
Sep 27 Javascript
JS定时器用法分析【时钟与菜单中的应用】
Dec 21 Javascript
angularJS深拷贝详解
Mar 23 Javascript
Angular2关于@angular/cli默认端口号配置的问题
Jul 15 Javascript
Vue中全局变量的定义和使用
Jun 05 Javascript
使用 webpack 插件自动生成 vue 路由文件的方法
Aug 20 Javascript
微信小程序用户授权最佳实践指南
May 08 Javascript
React列表栏及购物车组件使用详解
Jun 28 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
深入解析PHP中逗号与点号的区别
2013/08/05 PHP
cloudgamer出品ImageZoom 图片放大效果
2010/04/01 Javascript
JavaScript和ActionScript的交互实现代码
2010/08/01 Javascript
输入框过滤非数字的js代码
2014/09/18 Javascript
javascript实现的闭包简单实例
2015/07/17 Javascript
js实现密码强度检测【附示例】
2016/03/30 Javascript
jQueryUI DatePicker 添加时分秒
2016/06/04 Javascript
关于angularJs指令的Scope(作用域)介绍
2016/10/25 Javascript
JavaScript动态数量的文件上传控件
2016/11/18 Javascript
Angular项目从新建、打包到nginx部署全过程记录
2017/12/09 Javascript
JavaScript中的事件与异常捕获详析
2019/02/24 Javascript
详解Vue项目中实现锚点定位
2019/04/24 Javascript
5分钟快速看懂ES6中的反射与代理
2019/12/19 Javascript
[50:58]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 Mineski vs EG
2018/04/03 DOTA
Python判断操作系统类型代码分享
2014/11/22 Python
Python实现一个简单的MySQL类
2015/01/07 Python
Python脚本实现代码行数统计代码分享
2015/03/10 Python
python使用Tkinter实现在线音乐播放器
2018/01/30 Python
Python cookbook(数据结构与算法)实现对不原生支持比较操作的对象排序算法示例
2018/03/15 Python
python实现堆和索引堆的代码示例
2018/03/19 Python
python将视频转换为全字符视频
2019/04/26 Python
pandas基于时间序列的固定时间间隔求均值的方法
2019/07/04 Python
Spring实战之使用util:命名空间简化配置操作示例
2019/12/09 Python
日本土著品牌,综合型购物网站:Cecile
2016/08/23 全球购物
英国鹦鹉店:Parrot Essentials
2018/12/03 全球购物
EJB的基本架构
2016/09/22 面试题
销售自我评价
2013/10/22 职场文书
门前三包责任书
2014/04/15 职场文书
餐饮周年庆活动方案
2014/08/14 职场文书
党的群众路线教育实践活动个人整改落实情况汇报
2014/10/28 职场文书
房产分割协议书范文
2014/11/21 职场文书
2014年大学团支部工作总结
2014/12/02 职场文书
歼十出击观后感
2015/06/11 职场文书
2016年大学迎新工作总结
2015/10/14 职场文书
大学副班长竞选稿
2015/11/21 职场文书
python中使用 unittest.TestCase单元测试的用例详解
2021/08/30 Python