详解js异步文件加载器


Posted in PHP onJanuary 24, 2016

我们经常会遇到这种场景,某些页面依赖第三方的插件,而这些插件比较大,不适合打包到页面的主js里(假设我们使用的是cmd的方式,js会打包成一个文件),那么这个时候我们通常会异步获取这些插件文件,并在下载完成后完成初始化的逻辑。

以图片上传为例,我们可能会用到plupload.js这个插件,那么我们会这么写:

!window.plupload ?
    $.getScript( "/assets/plupload/plupload.full.min.js", function() {
      self._initUploader();
    }) :
    self._initUploader();

但是我们的页面通常由多个独立的模块(组件)构成,如果页面上的A、B两个模块都依赖于plupload.js, 那是不是在两个地方都要把上面的代码写一遍。如果这么干,在plupload.js被下载下来之前,可能会发起两个请求,由于是并行下载,js文件可能会被重复下载,而不是第一次下载下来,第二次取缓存的内容。

下图是页面多个组件依赖vue.js的情况(jquery和vue混用的场景):

详解js异步文件加载器

所以,在实际使用中需要加锁,即当脚本正在加载时,不应该再重复请求脚本,等待加载完成后,依次执行后面的逻辑,有promise这个好工具,实现起来很简单。

// vue加载器
var promiseStack = [];
function loadvue() {
  var promise = $.Deferred();
  if (loadvue.lock) {
    promiseStack.push(promise);
    
  } else {
    loadvue.lock = true;
    window.Vue ? 
       promise.resolve() : // 这里写错了,window.Vue为true的时候lock要置为false,我在后面改过来了
       $.getScript( "/assets/vue/vue.min.js", function() {
        loadvue.lock = false;
        promise.resolve();
        promiseStack.forEach(function(prom) {
          prom.resolve();
        });
      });
    
  }
  return promise;
}
window.loadvue = loadvue;

然后在依赖vue.js地方:

loadvue().then(function() { // do something });

再看看请求:

详解js异步文件加载器

好了,到这里似乎解决问题了,但是假如我的页面上存在多个插件依赖,比如既依赖plupload.js又依赖vue.js,难道我要把上面的代码再写一遍(怎么感觉好像说过这话)?这样不就冗余了么?所以我们需要一个异步加载器的生成器,能够帮助我们生成多个异步加载器。

/**
 * @des: js异步加载器生产器
 * @param {string} name  加载器名称
 * @param {string} global 全局变量
 * @param {string} url  加载地址
 **/

var promiseStack = {};

exports.generate = function(name, global, url) {
  var foo = function() {
    if (!promiseStack[name]) {
      promiseStack[name] = [];
    }
    var promise = $.Deferred();
    if (foo.lock) {
      promiseStack[name].push(promise);
      
    } else {
      foo.lock = true;
      if (window[global]) {
        foo.lock = false;
        promise.resolve();
      } else {
        $.getScript(url, function() {
          foo.lock = false;
          promise.resolve();
          promiseStack[name].forEach(function(prom) {
            prom.resolve();
          });
        });
      }
      
    }
    return promise;
  };
  
  return foo;
};

然后我们可以生成异步加载器并赋给window

// 全局加载器
window.loadvue = loader.generate(
'vue', 
'Vue', 
'/assets/vue/vue.min.js');
window.loadPlupload = loader.generate(
'plupload', 
'plupload', 
'/assets/plupload/plupload.full.min.js');

使用的时候同上,这样就基本解决了我们的问题。

以上就是关于js异步文件加载器的详细内容,希望对大家的学习有所帮助。

PHP 相关文章推荐
在PHP中使用XML
Oct 09 PHP
献给php初学者(入门学习经验谈)
Oct 12 PHP
提升PHP性能的21种方法介绍
Jun 25 PHP
PHP批量检测并去除文件BOM头代码实例
May 08 PHP
php中fsockopen用法实例
Jan 05 PHP
PHP使用缓存即时输出内容(output buffering)的方法
Aug 03 PHP
php源码 fsockopen获取网页内容实例详解
Sep 24 PHP
php封装的图片(缩略图)处理类完整实例
Oct 19 PHP
php动态读取数据清除最右边距的方法
Apr 12 PHP
网站被恶意镜像怎么办 php一段代码轻松搞定(全面版)
Oct 23 PHP
确保Laravel网站不会被嵌入到其他站点中的方法
Oct 18 PHP
PhpStorm2020 + phpstudyV8 +XDebug的教程详解
Sep 17 PHP
PHP导出Excel实例讲解
Jan 24 #PHP
PHP验证码生成原理和实现
Jan 24 #PHP
详解PHP对象的串行化与反串行化
Jan 24 #PHP
php上传图片获取路径及给表单字段赋值的方法
Jan 23 #PHP
高质量PHP代码的50个实用技巧必备(下)
Jan 22 #PHP
php使用timthumb生成缩略图的方法
Jan 22 #PHP
php session的锁和并发
Jan 22 #PHP
You might like
浅析PHP数据导出知识点
2018/02/17 PHP
Javascript中的常见排序算法
2007/03/27 Javascript
url 编码 js url传参中文乱码解决方案
2010/04/11 Javascript
点弹代码 点击页面任何位置都可以弹出页面效果代码
2012/09/17 Javascript
js 取时间差去掉周六周日实现代码
2012/12/25 Javascript
$.each遍历对象、数组的属性值并进行处理
2014/07/18 Javascript
windows下安装nodejs及框架express
2015/08/07 NodeJs
基于jQuery实现的QQ表情插件
2015/08/25 Javascript
JS右下角广告窗口代码(可收缩、展开及关闭)
2015/09/04 Javascript
JS实现浏览器状态栏显示时间的方法
2015/10/27 Javascript
为何JS操作的href都是javascript:void(0);呢
2015/11/12 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
2017/01/04 Javascript
Vue + Webpack + Vue-loader学习教程之功能介绍篇
2017/03/14 Javascript
jquery请求servlet实现ajax异步请求的示例
2017/06/03 jQuery
ExtJs的Ext.Ajax.request实现waitMsg等待提示效果
2017/06/14 Javascript
vue+axios 前端实现的常用拦截的代码示例
2018/08/23 Javascript
详解js创建对象的几种方式和对象方法
2021/03/01 Javascript
[54:15]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第二场2月1日
2021/03/11 DOTA
Python 随机生成中文验证码的实例代码
2013/03/20 Python
python实现数据图表
2017/07/29 Python
python之DataFrame实现excel合并单元格
2021/02/22 Python
python3写的简单本地文件上传服务器实例
2018/06/04 Python
python使用yield压平嵌套字典的超简单方法
2019/11/02 Python
python如何实现复制目录到指定目录
2020/02/13 Python
Python实现队列的方法示例小结【数组,链表】
2020/02/22 Python
白兰氏健康Mall:BRAND’S
2017/11/13 全球购物
PAUL HEWITT手表美国站:德国北部时尚生活配饰品牌,船锚元素
2017/11/18 全球购物
介绍下Java的输入输出流
2014/01/22 面试题
Linux开机引导的步骤是什么
2014/02/26 面试题
士力架广告词
2014/03/20 职场文书
2015年世界环境日活动总结
2015/02/11 职场文书
幼儿园教师岗位职责
2015/04/02 职场文书
贷款工作证明模板
2015/06/12 职场文书
父亲节感言
2015/08/03 职场文书
演讲稿:态度决定一切
2019/04/02 职场文书
TS 类型兼容教程示例详解
2022/09/23 Javascript