码迷,mamicode.com
首页 > Web开发 > 详细

基于requirejs+bluebird,50行代码实现轻巧实用的前端CMD加载器

时间:2017-02-05 10:50:20      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:promise   环境   地址   标签   变量   import   异步加载   node   r.js   

 

首先是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,所以允许链式加载

1 requireAsync(‘jquery‘, ‘bootstrap‘).then(function () {
2     window[‘jquery‘] = arguments[0];
3     window[‘bootstrap‘] = arguments[1];
4     return requireAsync(‘bootstrap-table‘);
5 }).then(function () {
6     
7 })

 

co函数

co函数和tj大神的co模块一样,但是tj大神的node模块只能用于nodejs,不能用于浏览器,这里是用的bluebird.coroutine实现的相同效果的co函数。

co函数在于能够配合generator/yield使用,从而达到async/await的效果,关于什么是generator,百度可以找出很多,我不赘述。

总而言之在浏览器的环境,基本是支持generator的。所以上面的代码能写成CMD的形式的代码,再配合上es6解构,简直爽歪歪

这是写在main函数中的代码

1 function* main() {
2     let [$, bootstrap] = yield requireAsync(‘jquery‘, ‘bootstrap‘);
3     yield requireAsync(‘bootstrap-table‘);
4 }

 

 

为什么使用requireAsync加co来加载模块

1、CMD的加载方式更直观,按需加载,需要加载jquery就加载jquery,需要加载react就加载react

2、能控制加载的先后顺序。这点我需要着重说一下。

     由于并非所有前端模块都是使用requirejs组织代码的,所以必然出现类似这样的模块,比如说依赖于jquery,但是不用requirejs加载

    

 1 !function ($) {
 2     "use strict";
 3 
 4     $.fn.extend({
 5         bgColor: function (color) {
 6             return $(this).css(‘background-color‘, color);
 7         }
 8     })
 9 
10 }(jQuery);

 

      requirejs的写法并不能控制加载的先后,并不是写在前面就先加载进来,他是用的script标签,是异步加载的,这就导致了你如果要先加载jquery再加载这个模块(比如说叫jquery-bgColor.js),就必须用嵌套的代码形式。嵌套的写法非常丑陋,当依赖变多并且都不使用requirejs组织的情况下必然嵌套越来越深。

      这同时也是AMD的非常不好的地方。

1 require([‘jquery‘],function($){
2     require([‘jquery-bgColor‘],function(){
3         
4     })
5 })

     

      但是使用了requireAsync+co后,这段代码就展平了,想要多深的依赖都没有关系

1 co(function* () {
2     const [$] = yield requireAsync(‘jquery‘);
3     yield requireAsync(‘jquery-bgColor‘);
4     yield requireAsync(‘jquery-bgColor-blue‘);
5     yield requireAsync(‘jquery-bgColor-blue-white‘);
6 })

 

 

使用

可以参照上面的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加载器

标签:promise   环境   地址   标签   变量   import   异步加载   node   r.js   

原文地址:http://www.cnblogs.com/kazetotori/p/6366895.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!