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 相关文章推荐
Extjs中DisplayField的日期或者数字格式化扩展
Sep 03 Javascript
js实现简单鼠标跟随效果的方法
Apr 10 Javascript
jQuery实现Meizu魅族官方网站的导航菜单效果
Sep 14 Javascript
JS实现网页上随滚动条滚动的层效果代码
Nov 04 Javascript
Javascript实现跑马灯效果的简单实例
May 31 Javascript
BootStrapValidator校验方式
Dec 19 Javascript
AngularJS实现的2048小游戏功能【附源码下载】
Jan 03 Javascript
angular ng-model 无法获取值的处理方法
Oct 02 Javascript
js如何获取图片url的Blob值并预览示例代码
Mar 07 Javascript
JS正则表达式常见函数与用法小结
Apr 13 Javascript
在Vue中使用antv的示例代码
Jun 29 Javascript
vue实现下拉菜单树
Oct 22 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
虫族 Zerg 魔法科技
2020/03/14 星际争霸
php实现计数器方法小结
2015/01/05 PHP
PHP消息队列用法实例分析
2016/02/12 PHP
IE6浏览器下resize事件被执行了多次解决方法
2012/12/11 Javascript
js Math 对象的方法
2013/09/01 Javascript
JavaScript图片放大技术(放大镜)实现代码分享
2013/11/14 Javascript
关于JS数组追加数组采用push.apply的问题
2014/06/09 Javascript
javascript判断数组内是否重复的方法
2015/04/21 Javascript
简介JavaScript中的getUTCFullYear()方法的使用
2015/06/10 Javascript
简单谈谈javascript中的变量、作用域和内存问题
2015/08/30 Javascript
利用Angularjs和bootstrap实现购物车功能
2016/08/31 Javascript
浅谈vue自定义全局组件并通过全局方法 Vue.use() 使用该组件
2017/12/07 Javascript
微信小程序模拟cookie的实现
2018/06/20 Javascript
Jquery和CSS实现选择框重置按钮功能
2018/11/08 jQuery
layui实现checkbox的目录树tree的例子
2019/09/12 Javascript
javascrpt密码强度校验函数详解
2020/03/18 Javascript
微信小程序自定义yPicker组件实现省市区三级联动功能
2020/10/29 Javascript
[01:30:55]VG vs Mineski Supermajor 败者组 BO3 第三场 6.6
2018/06/07 DOTA
Django继承自带user表并重写的例子
2019/11/18 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
python如何运行js语句
2020/09/09 Python
Python实例教程之检索输出月份日历表
2020/12/16 Python
英国最大的电子产品和家电零售企业:Currys PC World
2016/09/24 全球购物
亚马逊墨西哥站:Amazon.com.mx
2018/08/26 全球购物
印度服装购物网站:Limeroad
2018/09/26 全球购物
几个Linux面试题笔试题
2012/12/01 面试题
开工庆典邀请函范文
2014/01/16 职场文书
教导主任竞聘演讲稿
2014/05/16 职场文书
民主评议党员自我评价材料
2014/09/18 职场文书
介绍信怎么写
2015/05/05 职场文书
致毕业季:你如何做好自己的职业生涯规划书?
2019/07/01 职场文书
MySQL开启事务的方式
2021/06/26 MySQL
Python torch.flatten()函数案例详解
2021/08/30 Python
MySQL基于索引的压力测试的实现
2021/11/07 MySQL
电脑开机弹出documents文件夹怎么回事?弹出documents文件夹解决方法
2022/04/08 数码科技
python语言中pandas字符串分割str.split()函数
2022/08/05 Python