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 相关文章推荐
document 和 document.all 分别什么时候用
Jun 22 Javascript
腾讯的ip接口 方便获取当前用户的ip地理位置
Nov 25 Javascript
如何在node的express中使用socket.io
Dec 15 Javascript
使用javascript实现监控视频播放并打印日志
Jan 05 Javascript
jquery实现滑动特效代码
Aug 10 Javascript
js实现水平滚动菜单导航
Jul 21 Javascript
在原生不支持的旧环境中添加兼容的Object.keys实现方法
Sep 11 Javascript
详解webpack打包时排除其中一个css、js文件或单独打包一个css、js文件(两种方法)
Oct 26 Javascript
微信小程序实现多选删除列表数据功能示例
Jan 15 Javascript
微信小程序单选框自定义赋值
May 26 Javascript
Vue props中Object和Array设置默认值操作
Jul 30 Javascript
小程序实现上下切换位置
Nov 16 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
PHP4引用文件语句的对比
2006/10/09 PHP
php设计模式之单例、多例设计模式的应用分析
2013/06/30 PHP
ThinkPHP登录功能的实现方法
2014/08/20 PHP
自己写的兼容低于PHP 5.5版本的array_column()函数
2014/10/24 PHP
PHP进程同步代码实例
2015/02/12 PHP
php与Mysql的一些简单的操作
2015/02/26 PHP
PHP中OpenSSL加密问题整理
2017/12/14 PHP
javascript实现轮显新闻标题链接
2007/08/13 Javascript
javascript中万恶的function实例分析
2011/05/25 Javascript
按下Enter焦点移至下一个控件的实现js代码
2013/12/11 Javascript
对比分析json及XML
2014/11/28 Javascript
Redis基本知识、安装、部署、配置笔记
2015/03/05 Javascript
基于javascript html5实现3D翻书特效
2016/03/14 Javascript
JavaScript中判断数据类型的方法总结
2016/05/24 Javascript
Angular学习笔记之angular的$filter服务浅析
2016/11/12 Javascript
jQuery时间验证和转换为标准格式的时间格式
2017/03/06 Javascript
微信小程序 仿美团分类菜单 swiper分类菜单
2017/04/12 Javascript
高性能的javascript之加载顺序与执行原理篇
2018/01/14 Javascript
JS实现可用滑块滑动的缓动图代码
2019/09/01 Javascript
JS forEach跳出循环2种实现方法
2020/06/24 Javascript
js实现带积分弹球小游戏
2020/07/21 Javascript
python实现连接mongodb的方法
2015/05/08 Python
python读取excel表格生成erlang数据
2017/08/26 Python
使用Python将Mysql的查询数据导出到文件的方法
2019/02/25 Python
Python实现代码统计工具
2019/09/19 Python
python 如何上传包到pypi
2020/12/24 Python
Python关于拓扑排序知识点讲解
2021/01/04 Python
伦敦最有品味的百货:Liberty London
2016/11/12 全球购物
美国花园雕像和家居装饰网上商店:Design Toscano
2019/03/09 全球购物
好的演讲稿开场白
2013/12/30 职场文书
技术负责人任命书
2014/06/05 职场文书
怎么写工作检讨书
2014/11/16 职场文书
在职证明范本
2015/06/15 职场文书
工作简报范文
2015/07/21 职场文书
Nginx快速入门教程
2021/03/31 Servers
C3 线性化算法与 MRO之Python中的多继承
2021/10/05 Python