基于requirejs+bluebird,50行代码实现轻巧实用的前端CMD加载器
首先是github地址,可以用git克隆命令也可以直接在git页面下载
https://github.com/kazetotori/js-requireAsync
下载下来后目录结构是这样的
-package.json
-index.js
-node_modules
--bluebird
--jquery
--requirejs
requireAsync函数
requireAsync函数是index.js里定义的一个全局函数,该函数接受无限多个字符串参数,参数为需要加载的模块名或模块路径,路径不能包含.js后缀,这是因为本身是通过requirejs加载的,这个函数返回一个Promise,当resolve时,就返回一个数组,数组中包含了所有需要加载的模块,当reject时,就会抛出requirejs加载错误,一般是找不到模块即模块路径的错误。
由于是Promise,所以允许链式加载
requireAsync('jquery', 'bootstrap').then(function () {
window['jquery'] = arguments[0];
window['bootstrap'] = arguments[1];
return requireAsync('bootstrap-table');
}).then(function () {
})
co函数
co函数和tj大神的co模块一样,但是tj大神的node模块只能用于nodejs,不能用于浏览器,这里是用的bluebird.coroutine实现的相同效果的co函数。
co函数在于能够配合generator/yield使用,从而达到async/await的效果,关于什么是generator,百度可以找出很多,我不赘述。
总而言之在浏览器的环境,基本是支持generator的。所以上面的代码能写成CMD的形式的代码,再配合上es6解构,简直爽歪歪
这是写在main函数中的代码
function* main() {
let [$, bootstrap] = yield requireAsync('jquery', 'bootstrap');
yield requireAsync('bootstrap-table');
}
为什么使用requireAsync加co来加载模块
1、CMD的加载方式更直观,按需加载,需要加载jquery就加载jquery,需要加载react就加载react
2、能控制加载的先后顺序。这点我需要着重说一下。
由于并非所有前端模块都是使用requirejs组织代码的,所以必然出现类似这样的模块,比如说依赖于jquery,但是不用requirejs加载
!function ($) {
"use strict";
$.fn.extend({
bgColor: function (color) {
return $(this).css('background-color', color);
}
})
}(jQuery);
requirejs的写法并不能控制加载的先后,并不是写在前面就先加载进来,他是用的script标签,是异步加载的,这就导致了你如果要先加载jquery再加载这个模块(比如说叫jquery-bgColor.js),就必须用嵌套的代码形式。嵌套的写法非常丑陋,当依赖变多并且都不使用requirejs组织的情况下必然嵌套越来越深。
这同时也是AMD的非常不好的地方。
require(['jquery'],function($){
require(['jquery-bgColor'],function(){
})
})
但是使用了requireAsync+co后,这段代码就展平了,想要多深的依赖都没有关系
co(function* () {
const [$] = yield requireAsync('jquery');
yield requireAsync('jquery-bgColor');
yield requireAsync('jquery-bgColor-blue');
yield requireAsync('jquery-bgColor-blue-white');
})
使用
可以参照上面的github地址中的how to start,其实就是html中加载requirejs,并设置data-main为index.js,之后的代码写在main函数里就行了,当然你也可以写一个main.js,然后修改index.js里的源代码加载这个main.js模块。
原理
index.js里的代码去掉注释只有50+行,我们一步一步看
1、首先是配置了一下requirejs,添加了几个模块路径,你的模块也可以在这里配置

2、我们跳到后面来看两个函数定义,这是我的习惯,把函数定义放在主逻辑之后
第一个slice函数毫无疑问,只是调用了一下Array.prototype.slice函数
第二个就是requireAsync函数,其实就是用requirejs加载,然后用promise将加载好的模块resolve出来

3、绕回我们的主逻辑,我在这里首先定义了一个变量co,但是我需要在加载bluebird后才对这个变量进行初始化。
首先我使用requirejs加载bluebird和jquery,并初始化co函数。
bluebird.coroutine将函数包装成一个返回promise的函数,但仅仅返回这个函数并不执行,我需要执行并且直接返回这个promise
然后我使用co去执行一个generator,首先等待dom加载完毕这个promise状态变为resolve,然后执行main函数中的内容
这里不想用jquery也可以直接用
window.addEventListener('DOMContentReady',function(){resolve()})
来取代
$(function(){resolve()})
这样就能不加载jquery了。

4、最后是main函数,毫无疑问,args为jquery传的参数

总结
generator/yield实在是好特性,原本我是写的async/await版本,但是只能用在最新版本的chorme中,所以改成了用生成器,本质上是一样的,即将异步代码同步化,用yield取代回调。现在的js,新特性如果还有什么期待的我想我还是比较期待import/export,毕竟这个才是正统的模块加载方式。而且各个模块维护自己的作用域,等于是默认闭包了。如此一来想输出到window上就必须window.jQuery=jQuery了。
嵌套和回调自然是越少越好。
基于requirejs+bluebird,50行代码实现轻巧实用的前端CMD加载器的更多相关文章
- AngularJs2与AMD加载器(dojo requirejs)集成
现在是西太平洋时间凌晨,这个问题我鼓捣了一天,都没时间学英语了,英语太差,相信第二天我也看不懂了,直接看结果就行. 核心原理就是require在AngularJs2编译过程中是关键字,而在浏览器里面运 ...
- python爬虫实战:利用scrapy,短短50行代码下载整站短视频
近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法.这忙我得帮,少不得就抓包分析了一下这个app,找到了视频的下载链接,帮他解决了这个小问题 ...
- 50行代码实现python计算器主要功能
实现功能:计算带有括号和四则运算的式子 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 基本思路:使用正则表达式提取出每一层 ...
- 50行代码实现缓存,JAVA内存模型原理
遇见这样的高人怎么办??下面是一个简单缓存的实现,相当牛叉!自己看吧,只有50行代码. 摘自:http://www.oschina.net/code/snippet_55577_3887 import ...
- HTML5游戏实战(1):50行代码实现正面跑酷游戏
前段时间看到一个"熊来了"的HTML5跑酷游戏,它是一个典型的正面2D跑酷游戏,这里借用它来介绍一下用Gamebuilder+CanTK开发正面跑酷游戏的基本方法. CanTK(C ...
- 50行代码实现GAN | 干货演练
2014年,Ian Goodfellow和他的同事发表了一篇论文,向世界介绍了生成对抗网络(GAN).通过对计算图和博弈论的创新性组合,他们表明如果有足够的建模能力,两个相互对抗的模型可以通过普通的反 ...
- 《你必须知道的.NET》读书实践:一个基于OO的万能加载器的实现
此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.关于万能加载器 简而言之,就是孝顺的小王想开发一个万能程序,可以一键式打开常见的计算机资料,例如: ...
- 使用RequireJS并实现一个自己的模块加载器 (一)
RequireJS & SeaJS 在 模块化开发 开发以前,都是直接在页面上引入 script 标签来引用脚本的,当项目变得比较复杂,就会带来很多问题. JS项目中的依赖只有通过引入JS的顺 ...
- RequireJS 是一个JavaScript模块加载器
RequireJS 是一个JavaScript模块加载器.它非常适合在浏览器中使用, 它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJ ...
随机推荐
- 在DataTable数据类型最后增加一列,列名为“Column”,内容都为“AAA”
DataTable dt = new DataTable(); dt.Columns.Add("Column", typeof(string)); foreach (DataRow ...
- sql server停止和重启命令
http://www.ynpxrz.com/n822732c2024.aspx 我们知道:sql server重启分分两步走 1.停止 net stop mssqlserver 2.重启 net st ...
- Java 导出Excel的各种尝试
最近的一个项目比较忙,一直没时间过来跟新博客.今天过来分享一下在此项目中遇到的一个小问题:导出Excel:相信导出Excel这个功能是特别常见的,也有很多的方式.好了,不多说了,直接说说自己遇到的各种 ...
- Bootstrap入门(十四)组件8:媒体对象
Bootstrap入门(十四)组件8:媒体对象 这是一个抽象的样式,用以构建不同类型的组件,这些组件都具有在文本内容的左或右侧对齐的图片(就像博客评论或 Twitter 消息等). 1.基本样式 2. ...
- SQL Server-索引故事的遥远由来,原来是这样的?
前言 前段时间工作比较忙,每天回来也时不时去写有关ASP.NET Core的文章,无论是项目当中遇到的也好还是自学的也好都比较严谨的去叙述,喜欢分享,乐于分享这是我一直以来的态度,当然从中也会有些许错 ...
- C# 6 与 .NET Core 1.0 高级编程 - C# 6 改进
个人原创译文,转载请注明出处.有不对的地方欢迎指出与交流. 英文原文:Professional C# 6 and .NET Core 1.0 - What's New in C# 6 C# 6 改进 ...
- tableView的编辑
首先记住声明编辑样式的属性 UITableViewCellEditingStyle 和四个步骤 第一步:让tableView处于编辑状态 [self.rootView.tabView setEdit ...
- 自己动手系列——实现一个简单的LinkedList
LinkedList与ArrayList都是List接口的具体实现类.LinkedList与ArrayList在功能上也是大体一致,但是因为两者具体的实现方式不一致,所以在进行一些相同操作的时候,其效 ...
- HTML5部分元素
Document HTML4文档声明 : <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" &qu ...
- React-intl 实现多语言
前言 React 做国际化,我推荐使用 React-intl , 这个库提供了 React 组件和Api两种方式来格式化日期,数字和字符串等.知道这个库了,那让我们开始使用它 组件用法 为了和Reac ...