详解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扩展图文教程
Dec 12 PHP
php 上传文件类型判断函数(避免上传漏洞 )
Jun 08 PHP
解析PHP中的内存管理,PHP动态分配和释放内存
Jun 28 PHP
解析php中curl_multi的应用
Jul 17 PHP
PHP 面向对象程序设计(oop)学习笔记 (二) - 静态变量的属性和方法及延迟绑定
Jun 12 PHP
PHP彩蛋信息介绍和阻止泄漏的方法(隐藏功能)
Aug 06 PHP
微信公众平台开发实现2048游戏的方法
Apr 15 PHP
PHP实现简单搜歌的方法
Jul 28 PHP
thinkphp3.x中cookie方法的用法分析
May 19 PHP
laravel中的错误与日志用法详解
Jul 26 PHP
PHP isset()与empty()的使用区别详解
Feb 10 PHP
利用Homestead快速运行一个Laravel项目的方法详解
Nov 14 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
在WIN98下以apache模块方式安装php
2006/10/09 PHP
PHP缓存技术的多种方法小结
2012/08/14 PHP
基于Swoole实现PHP与websocket聊天室
2016/08/03 PHP
mac系统下安装多个php并自由切换的方法详解
2017/04/21 PHP
JS处理VBArray的函数使用说明
2008/05/11 Javascript
jquery getScript动态加载JS方法改进详解
2012/11/15 Javascript
Extjs 3.3切换tab隐藏相应工具栏出现空白解决
2013/04/02 Javascript
Jquery 获取对象的几种方式介绍
2014/01/17 Javascript
Google官方支持的NodeJS访问API,提供后台登录授权
2014/07/29 NodeJs
基于JS组件实现拖动滑块验证功能(代码分享)
2016/11/18 Javascript
jQGrid Table操作列中点击【操作】按钮弹出按钮层的实现代码
2016/12/05 Javascript
Web 开发中Ajax的Session 超时处理方法
2017/01/19 Javascript
微信小程序实现tab左右切换效果
2020/11/15 Javascript
axios 封装上传文件的请求方法
2018/09/26 Javascript
Layui数据表格 前后端json数据接收的方法
2019/09/19 Javascript
layui字体图标 loading图标静止不旋转的解决方法
2019/09/23 Javascript
javascript this指向相关问题及改变方法
2020/11/19 Javascript
使用JS实现鼠标放上图片进行放大离开实现缩小功能
2021/01/27 Javascript
[46:02]DOTA2上海特级锦标赛D组资格赛#2 Liquid VS VP第二局
2016/02/28 DOTA
python文件和目录操作方法大全(含实例)
2014/03/12 Python
Python的Django框架中设置日期和字段可选的方法
2015/07/17 Python
Python爬虫之pandas基本安装与使用方法示例
2018/08/08 Python
python实现与redis交互操作详解
2020/04/21 Python
在django中form的label和verbose name的区别说明
2020/05/20 Python
Python如何进行时间处理
2020/08/06 Python
浅析Python中字符串的intern机制
2020/10/03 Python
CSS3自定义滚动条样式的示例代码
2017/08/21 HTML / CSS
基于html5绘制圆形多角图案
2016/04/21 HTML / CSS
Stuart Weitzman美国官网:美国奢华鞋履品牌
2016/08/18 全球购物
企业管理部经理岗位职责
2013/12/24 职场文书
大二自我鉴定
2014/01/31 职场文书
应聘护理专业毕业自荐书范文
2014/02/12 职场文书
邓小平理论心得体会
2014/09/09 职场文书
2014年度安全工作总结
2014/12/04 职场文书
2015年毕业生个人自荐书
2015/03/24 职场文书
python实现简单倒计时功能
2021/04/21 Python