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 相关文章推荐
30个最好的jQuery 灯箱插件分享
Apr 25 Javascript
javascipt基础内容--需要注意的细节
Apr 10 Javascript
jQuery的实例及必知重要的jQuery选择器详解
May 20 Javascript
JavaScript简单获取系统当前时间完整示例
Aug 02 Javascript
jquery获取select,option所有的value和text的实例
Mar 06 Javascript
详解Vue单元测试case写法
May 24 Javascript
详解a标签添加onclick事件的几种方式
Mar 29 Javascript
vue19 组建 Vue.extend component、组件模版、动态组件 的实例代码
Apr 04 Javascript
vue数据初始化initState的实例详解
Apr 11 Javascript
详解Vue中CSS样式穿透问题
Sep 12 Javascript
vue 组件销毁并重置的实现
Jan 13 Javascript
vue中echarts引入中国地图的案例
Jul 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数组中的重复值的实现代码
2011/07/17 PHP
PHP Class&amp;Object -- 解析PHP实现二叉树
2013/06/25 PHP
19个超实用的PHP代码片段
2014/03/14 PHP
浅谈php中include文件变量作用域
2015/06/18 PHP
PHP获取某个月最大天数(最后一天)的方法
2015/07/29 PHP
屏蔽PHP默认设置中的Notice警告的方法
2016/05/20 PHP
Mootools 1.2教程 滑动效果(Slide)
2009/09/15 Javascript
js实现类似新浪微博首页内容渐显效果的方法
2015/04/10 Javascript
smartcrop.js智能图片裁剪库
2015/10/14 Javascript
jQuery控制控件文本的长度的操作方法
2016/12/05 Javascript
利用js+css+html实现固定table的列头不动
2016/12/08 Javascript
简化vuex的状态管理方案的方法
2018/06/02 Javascript
vue eslint简要配置教程详解
2019/07/26 Javascript
关于vue项目中搜索节流的实现代码
2019/09/17 Javascript
微信小程序实现比较功能的方法汇总(五种方法)
2020/03/07 Javascript
详解微信小程序轨迹回放实现及遇到的坑
2021/02/02 Javascript
python提示No module named images的解决方法
2014/09/29 Python
Windows上使用virtualenv搭建Python+Flask开发环境
2016/06/07 Python
Python绘制3d螺旋曲线图实例代码
2017/12/20 Python
Python爬虫爬取煎蛋网图片代码实例
2019/12/16 Python
Django接收照片储存文件的实例代码
2020/03/07 Python
python3爬虫中异步协程的用法
2020/07/10 Python
HTML5 LocalStorage 本地存储刷新值还在
2017/03/10 HTML / CSS
Html5定位终极解决方案
2020/02/05 HTML / CSS
美国办公用品购物网站:Quill.com
2016/09/01 全球购物
Viking Direct荷兰:购买办公用品
2019/06/20 全球购物
捷克购买家具网站:JENA nábytek
2020/03/19 全球购物
心理健康教育心得体会
2013/12/29 职场文书
简单租房协议书
2014/04/09 职场文书
2014超市收银员工作总结
2014/11/13 职场文书
辩论赛开场白大全(主持人+辩手)
2015/05/29 职场文书
雨中的树观后感
2015/06/03 职场文书
您对思维方式了解多少?
2019/12/09 职场文书
python 自动刷新网页的两种方法
2021/04/20 Python
python 制作一个gui界面的翻译工具
2021/05/14 Python
MySQL 如何设计统计数据表
2021/06/15 MySQL