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 相关文章推荐
[原创]js获取数组任意个不重复的随机数组元素
Mar 15 Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
Nov 14 Javascript
JS短路原理的应用示例 精简代码的途径
Dec 13 Javascript
Jsonp 关键字详解及json和jsonp的区别,ajax和jsonp的区别
Dec 30 Javascript
JS常用正则表达式总结【经典】
May 12 Javascript
微信小程序实现选项卡功能
Jun 19 Javascript
Node.js上传文件功能之服务端如何获取文件上传进度
Feb 05 Javascript
Vue三种常用传值示例(父传子、子传父、非父子)
Jul 24 Javascript
Angular6 写一个简单的Select组件示例
Aug 20 Javascript
详解React native fetch遇到的坑
Aug 30 Javascript
jQuery实现鼠标移入移出事件切换功能示例
Sep 06 jQuery
Vue 3.0 全家桶抢先体验
Apr 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
WHOIS类的修改版
2006/10/09 PHP
从刷票了解获得客户端IP的方法
2015/09/21 PHP
ExtJS TabPanel beforeremove beforeclose使用说明
2010/03/31 Javascript
js,jquery滚动/跳转页面到指定位置的实现思路
2014/06/03 Javascript
js实现iframe跨页面调用函数的方法
2014/12/13 Javascript
Javascript基础教程之break和continue语句
2015/01/18 Javascript
基于insertBefore制作简单的循环插空效果
2015/09/21 Javascript
JavaScript实现获取某个元素相邻兄弟节点的prev与next方法
2016/01/25 Javascript
Bootstrap3使用typeahead插件实现自动补全功能
2016/07/07 Javascript
支持移动端原生js轮播图
2017/02/16 Javascript
vue实现百度搜索下拉提示功能实例
2017/06/14 Javascript
laydate 显示结束时间不小于开始时间的实例
2017/08/11 Javascript
vue中阻止click事件冒泡,防止触发另一个事件的方法
2018/02/08 Javascript
vue+iview+less+echarts实战项目总结
2018/02/22 Javascript
微信小程序动画(Animation)的实现及执行步骤
2018/10/28 Javascript
Vue数据双向绑定的深入探究
2018/11/27 Javascript
vue使用pdfjs显示PDF可复制的实现方法
2018/12/14 Javascript
JS多个异步请求 按顺序执行next实现解析
2019/09/16 Javascript
浅析vue-router中params和query的区别
2019/12/24 Javascript
vue项目中使用vue-layer弹框插件的方法
2020/03/11 Javascript
javascript实现搜索筛选功能实例代码
2020/11/12 Javascript
python中的对象拷贝示例 python引用传递
2014/01/23 Python
Python脚本实现自动将数据库备份到 Dropbox
2017/02/06 Python
Python爬虫框架Scrapy实例代码
2018/03/04 Python
python从zip中删除指定后缀文件(推荐)
2019/12/05 Python
Python求凸包及多边形面积教程
2020/04/12 Python
Python基于network模块制作电影人物关系图
2020/06/19 Python
中国海淘族值得信赖的海淘返利网站:55海淘
2017/01/16 全球购物
.TTL是什么?有什么用处,通常那些工具会用到它?(ping? traceroute? ifconfig? netstat?)
2016/05/09 面试题
小学门卫岗位职责
2013/12/17 职场文书
《恐龙》教学反思
2014/04/27 职场文书
项目投资意向书范本
2015/05/09 职场文书
2019广播稿怎么写
2019/04/17 职场文书
2019消防宣传标语!
2019/07/10 职场文书
分享Python获取本机IP地址的几种方法
2022/03/17 Python
AngularJS实现多级下拉框
2022/03/25 Javascript