详解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 相关文章推荐
修改Zend引擎实现PHP源码加密的原理及实践
Apr 14 PHP
php 缓存函数代码
Aug 27 PHP
php 取得瑞年与平年的天数的代码
Aug 10 PHP
PHP用GD库生成高质量的缩略图片
Mar 09 PHP
php的zip解压缩类pclzip使用示例
Mar 14 PHP
可以保证单词完整性的PHP英文字符串截取代码分享
Jul 15 PHP
PHP打开和关闭文件操作函数总结
Nov 18 PHP
php中adodbzip类实例
Dec 08 PHP
PHP使用fopen与file_get_contents读取文件实例分享
Mar 04 PHP
PHP登录(ajax提交数据和后台校验)实例分享
Dec 29 PHP
php实现购物车产品删除功能(2)
Jul 23 PHP
strpos() 函数判断字符串中是否包含某字符串的方法
Jan 16 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函数实现分页含文本分页和数字分页
2014/10/23 PHP
Yii2针对游客、用户防范规则和限制的解决方法分析
2016/10/08 PHP
关于使用runtimeStyle属性问题讨论文章
2007/03/08 Javascript
JavaScript中的new的使用方法与注意事项
2007/05/16 Javascript
js截取函数(indexOf,join等)
2010/09/01 Javascript
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
2012/07/17 Javascript
手写的一个兼容各种浏览器的javascript getStyle函数(获取元素的样式)
2014/06/06 Javascript
js调试系列 断点与动态调试[基础篇]
2014/06/18 Javascript
IE6 hack for js 集锦
2014/09/23 Javascript
jQuery+slidereveal实现的面板滑动侧边展出效果
2015/03/14 Javascript
学习AngularJs:Directive指令用法(完整版)
2016/04/26 Javascript
JS基础随笔(菜鸟必看篇)
2016/07/13 Javascript
vue2滚动条加载更多数据实现代码
2017/01/10 Javascript
Javascript中的 “&” 和 “|” 详解
2017/02/02 Javascript
touch.js 拖动、缩放、旋转 (鼠标手势)功能代码
2017/02/04 Javascript
详解vue嵌套路由-params传递参数
2017/05/23 Javascript
jqgrid实现简单的单行编辑功能
2017/09/30 Javascript
在react-router4中进行代码拆分的方法(基于webpack)
2018/03/08 Javascript
详解vue-cli 本地开发mock数据使用方法
2018/05/29 Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
2020/02/10 Javascript
JavaScript实现手风琴效果
2021/02/18 Javascript
[55:18]Liquid vs Chaos 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
在Pycharm中修改文件默认打开方式的方法
2019/01/17 Python
自定义Django默认的sitemap站点地图样式
2020/03/04 Python
django前端页面下拉选择框默认值设置方式
2020/08/09 Python
Autopep8的使用(python自动编排工具)
2021/03/02 Python
CSS3 选择器 基本选择器介绍
2012/01/21 HTML / CSS
html5嵌入内容_动力节点Java学院整理
2017/07/07 HTML / CSS
Clarins娇韵诗英国官网:来自法国的天然护肤品牌
2017/04/18 全球购物
Melissa鞋马来西亚官方网站:MDreams马来西亚
2018/04/05 全球购物
大学生求职简历的自我评价
2013/10/21 职场文书
研发工程师的岗位职责
2013/11/18 职场文书
C++程序员求职信范文
2014/04/14 职场文书
服务型党组织建设典型材料
2014/05/07 职场文书
2015年大学组织委员个人工作总结
2015/10/23 职场文书
quickjs 封装 JavaScript 沙箱详情
2021/11/02 Javascript