详解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获取远程图片并把它保存到本地的代码
Apr 07 PHP
彻底杜绝PHP的session cookie错误
Aug 09 PHP
让你成为更出色的PHP开发者的10个技巧
Feb 25 PHP
PHP输出时间差函数代码
Jan 28 PHP
解析PHP中如何将数组变量写入文件
Jun 06 PHP
2014年10个最佳的PHP图像操作库
Jul 14 PHP
php获取四位字母和数字的随机数的实现方法
Jan 09 PHP
PHP实现的json类实例
Jul 28 PHP
Yii2中使用join、joinwith多表关联查询
Jun 30 PHP
ThinkPHP发送邮件示例代码
Oct 08 PHP
Symfony查询方法实例小结
Jun 28 PHP
Laravel 登录后清空COOKIE的操作方法
Oct 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
十大“创意”战术!
2020/03/04 星际争霸
咖啡店都有些什么常规豆子呢?有什么风味在里面
2021/03/04 咖啡文化
不错的一篇面向对象的PHP开发模式(简写版)
2007/03/15 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
2015/03/19 PHP
Zend Framework教程之请求对象的封装Zend_Controller_Request实例详解
2016/03/07 PHP
记Laravel调用Gin接口调用formData上传文件的实现方法
2019/12/12 PHP
一些Javascript的IE和Firefox(火狐)兼容性的问题总结及常用例子
2009/05/21 Javascript
window.onload 加载完毕的问题及解决方案(下)
2009/07/09 Javascript
jQuery源码分析之Event事件分析
2010/06/07 Javascript
jQuery版Tab标签切换
2011/03/16 Javascript
js滑动提示效果代码分享
2016/03/10 Javascript
深入浅析JavaScript中的scrollTop
2016/07/11 Javascript
AngularJS下对数组的对比分析
2016/08/24 Javascript
微信JS-SDK自定义分享功能实例详解【分享给朋友/分享到朋友圈】
2016/11/25 Javascript
Angular X中使用ngrx的方法详解(附源码)
2017/07/10 Javascript
AngularJS表单验证功能
2017/10/19 Javascript
JS使用栈判断给定字符串是否是回文算法示例
2019/03/04 Javascript
详解关于JSON.parse()和JSON.stringify()的性能小测试
2019/03/14 Javascript
vue发送websocket请求和http post请求的实例代码
2019/07/11 Javascript
layer弹出层自定义提交取消按钮的例子
2019/09/10 Javascript
vue滚动插件better-scroll使用详解
2019/10/18 Javascript
JavaScript实现鼠标经过表格某行时此行变色
2020/11/20 Javascript
[00:59]DOTA2荣耀之路1:Doom is back!weapon X!
2018/05/22 DOTA
[04:15]DOTA2-DPC中国联赛1月19日Recap集锦
2021/03/11 DOTA
python安装以及IDE的配置教程
2015/04/29 Python
Python字符串、元组、列表、字典互相转换的方法
2016/01/23 Python
基于Django静态资源部署404的解决方法
2019/07/28 Python
Python logging模块handlers用法详解
2020/08/14 Python
python help函数实例用法
2020/12/06 Python
Bravofly德国:预订廉价航班和酒店
2019/09/22 全球购物
阿拉伯时尚购物网站:Nisnass
2021/02/07 全球购物
LINUX下线程,GDI类的解释
2012/04/17 面试题
红与黑读书笔记
2015/06/29 职场文书
2016中学教师读书心得体会
2016/01/13 职场文书
logback 实现给变量指定默认值
2021/08/30 Java/Android
SpringBoot实现quartz定时任务可视化管理功能
2021/08/30 Java/Android