博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
操刀 requirejs,自己动手写一个
阅读量:5076 次
发布时间:2019-06-12

本文共 13557 字,大约阅读时间需要 45 分钟。

这篇文章讲的是,我怎么去写一个 requirejs 。

requirejs,众所周知,是一个非常出名的js模块化工具,可以让你使用模块化的方式组织代码,并异步加载你所需要的部分。balabala 等等好处不计其数。

之所以写这篇文章,是做一个总结。目前打算动一动,换一份工作。感谢 大大帮忙推了携程,得到了面试的机会。

面试的时候,聊着聊着感觉问题都问在了自己的“点”上,应答都挺顺利,于是就慢慢膨胀了。在说到模块化的时候,我脑子一抽,凭着感觉说了一下requirejs实现的大概步骤,充满了表现欲望,废话一堆。侥幸不可能当场让我写一遍,算是过了,事后尝试了一下,在这里跟大家分享一下我的实现。

上面是我划分的项目结构:

  1. tool,工具模块,存放便捷方法,很多地方需要用到。
  2. async,异步处理模块,主要实现了 promisedeferred 。逻辑上的异步。
  3. requirejs -> loader ,amd加载器,处理模块的依赖和异步加载。物理上的异步。

因为对于异步流程控制方面,研究过一段时间,所以这里第一时间想到的就是 promise ,如果用这个来做,所有的模块放入字典,路径做key,promise做value,所有依赖都结束之后,才进行下一步操作。 不用管复杂的依赖关系,把逻辑尽量简单化:

  1. 首先有一个字典,存放所有的模块。key放地址,value放promise,promise在模块加载完毕的时候resolve。
  2. 如果依赖某个模块,先根据路径从字典找key,存在就用该promise,不存在就去加载该模块并放入字典,并使用该模块的promise。
  3. 所有的模块,我只用它的 promise ,在它的回调中写我的后续操作。它的resolve应该单独抽离出来,属于异步加载方面。

大致思路有了,当然实际写的时候肯定困难重重,不过没关系,遇到问题再去解决。

考虑到代码的简易性,以及我的个人习惯。我打算用类似于 jquery 的 $.Deferred() 和它的promise,与es6的promise有一定的出入。这样代码书写更简易,并且逻辑上更清晰,es6的promise用起来确实稍显麻烦。我需要的是一个 pub/sub 模式,一个地方触发,多个回调执行的并行方式,es6的promise,需要在then中一次次返回,并且resolve起来也不方便,最最主要的是需要 polyfill 一下,而我想自己写,写我熟悉且喜欢的代码 。

回调模块 callbacks,熟悉jquery的朋友接下来可能会觉得使用方式很熟悉,没错,我受jq的影响算是比较深的。以前在学习jq源码的时候,就觉得这个很好用,你可以从我的代码里面看到jq的影子 :

1 import _ from '../tool/tool'; 2  3 /** 4  * 基础回调模块 5  *  6  * @export 7  * @returns callbacks 8  */ 9 export default function () {10     let list = [],11         _args = (arguments[0] || '').split(' '),           // 参数数组12         fireState = 0,                                     // 触发状态  0-未触发过 1-触发中  2-触发完毕13         stopOnFalse = ~_args.indexOf('stopOnFalse'),       // stopOnFalse - 如果返回false就停止14         once = ~_args.indexOf('once'),                     // once - 只执行一次,即执行完毕就清空15         memory = ~_args.indexOf('memory') ? [] : null,     // memory - 保持状态16         fireArgs = [];                                     // fire 参数17 18     /**19      * 添加回调函数20      * 21      * @param {any} cb22      * @returns callbacks23      */24     function add(cb) {25         if (memory && fireState == 2) {  // 如果是memory模式,并且已经触发过26             cb.apply(null, fireArgs);27         }28 29         if (disabled()) return this;      // 如果被disabled30 31         list.push(cb);32         return this;33     }34 35     /**36      * 触发37      * 38      * @param {any} 任意参数39      * @returns callbacks40      */41     function fire() {42         if (disabled()) return this; // 如果被禁用43 44         fireArgs = _.makeArray(arguments); // 保存 fire 参数45 46         fireState = 1; // 触发中 47 48         _.each(list, (index, cb) => { // 依次触发回调49             if (cb.apply(null, fireArgs) === false && stopOnFalse) { // stopOnFalse 模式下,遇到false会停止触发50                 return false;51             }52         });53 54         fireState = 2; // 触发结束55 56         if (once) disable(); // 一次性列表57 58         return this;59     }60 61     function disable() {    // 禁止62         list = undefined;63         return this;64     }65 66     function disabled() {  // 获取是否被禁止67         return !list;68     }69 70     return {71         add: add,72         fire: fire,73         disable: disable,74         disabled: disabled75     };76 }
View Code

 

这是一个工厂方法,每次所需的对象由该方法生成,用闭包来隐藏局部变量,私有方法。而最后暴露(发布)出来的对象,用 pub/sub 模式,提供了 订阅触发禁用查看禁用 4个方法。 这里要说的是 ,提供了3个参数:stopOnFalseoncememory。触发的时候,按照订阅顺序依次触发,如果是 stopOnFalse 模式,当某个订阅的函数,返回是 false 的时候,停止整个触发过程。 如果是 once ,表示每个函数只能执行一次,在执行过后,会被移除队列。而 memory 状态下,在 callback 触发后,会被保持状态,之后添加的方法,添加后会直接执行。

这三种模式,传参的时候直接传入字符串,可以随意组合,用空格分开,比如:callbacks('once memory')

该模块用于整个项目中,处理所有的回调。使用方式类似于jquery的:$.Callbacks(...)

 

写到这里,就已经结束了。本文讲了对于requirejs,我的实现思路,列举了可能遇到的问题,及我的解决方式。希望能给大家的学习提供点帮助。

上面是github的地址,求star啊,作为一个虚荣的人,我对这个很看重的,哈哈,也就这点追求了。再次感激 大哥的推荐,还有 的经验指导。

转载于:https://www.cnblogs.com/lianmin/p/my_requirejs.html

你可能感兴趣的文章
2-Eleventh Scrum Meeting20151211
查看>>
看毛片算法
查看>>
selenium-百度搜索框输入后,定位联想下拉框元素
查看>>
Http的请求的全过程
查看>>
(剑指Offer)面试题38:数字在排序数组中出现的次数
查看>>
orderby
查看>>
3105: [cqoi2013]新Nim游戏
查看>>
Xcode10和iOS12,library not found for -lstdc++.6.0.9,
查看>>
Raid详解
查看>>
c++面试遇到问题
查看>>
jvm 内存参数
查看>>
【转】NDK上建立自己的项目
查看>>
web测试方法总结
查看>>
原生js实现ajax方法
查看>>
关于Win10自带输入法莫名切成繁体
查看>>
php添加gd
查看>>
实训作业1
查看>>
openSUSE12.1安装及基本设置
查看>>
简约的form表单校验插件
查看>>
我读《2017软件测试行业调查报告》
查看>>