展开目录
seajs同步加载依赖的实现和弊病
seajsjavascript
X
陈尼玛的博客
记录开发生涯的踩坑经历,用时间来验证成长
加载中

我一向认为seajs不应该用在前端,主要是因为同步加载依赖的做法极大影响用户体验。虽然我不会在自己的项目中使用它,但是对同步加载的实现我还是有点兴趣的。 seajs的源码风格并不是很杂乱,基本一眼扫过就可以看明白在做什么。鉴于源代码太长,我使用猜测+搜索的方式来查看。因为我所知道的加载js方法只有createElement('script')ajax+eval两种,所以对于加载依赖的方法我首先尝试搜索createElement这个关键字,在第285行找到了:

seajs-code

但是这些代码并不是我要,因为从这些代码只能看出是把依赖文件用非阻塞方式来加载,与同步加载毫无关联。难道seajs用的是ajax+eval么?我虽然不相信但还是尝试搜索了XMLHttpRequest关键字,结果没找到。

两条常规道路都堵死了,那么扩展思维,也许require的方法做了一些奇怪的事情。所以我接着搜索了require关键字,我看到416行的正则和后面的替换操作:

seajs-code

到这里终于解开了同步加载的原理,其实是用了javascript-function的toString特性。parseDependencies方法接受参数为function字符串(请看代码第714行),调用之后首先使用正则表达式提取function里的所有依赖文件,在它们全部加载完之后执行function,所以实现了同步依赖。 虽然想法看似可行,但是从实现的角度上看seajs并没做好。比如说下面这样的代码均完全符合js语法,也没有违背seajs的规范,但实际上这些代码在seajs中都不会正常工作:

define(function(require){
  // 第一种,连接字符串
  require('jque'+'ry');
  // 第二种,紧跟在多行注释之后
  /*jquery*/require("jquery");
  // 第三种,转义字符形式
  require("jqu\u0065ry");
  // 第四中,转义字符反斜杠解析丢失,资源地址后v参数是空的
  require("jquery.js?v=\\\\");
});

也许我所列举的调用方式比较奇葩,但是生产环境和业务流程不会总是循规蹈矩,所以没人能保证不会发生这种情况。 除此之外,最根本的问题是seajs的同步加载依赖设计思想完全不符合前端环境。把js模块化的意义,在于降低耦合,提高内聚,不同功能之间不会互相影响。而seajs的加载方式直接反其道而行,下面代码很清楚的反应这个问题:

define(function(require){
  require('a').run();
  require('b').run();
});

不考虑a,b的内部依赖,仅看上面的两行代码中a和b并无直接关联,因此它们的执行顺序应该和写法无关,任何一个加载完成都应该立即执行,而不需要等待别的模块加载完成。而seajs永远会保证a,b都加载完成再一起执行,如果业务需求必须要b在加载完成之后就执行,那就只能把 require('b').run()拆到另一个文件中了。 其实requirejs的异步模块加载方式是目前看来最符合前端设计要求的,很多人认为它不好的原因基本是因为不清楚它的工作方式,或者无法理解异步编程的逻辑罢了。

相关文档

暂无

随便看看

  1. sqlite 查看table的构建语句

  2. react项目webpack打包时拆分异步加载的文件

  3. 华为等国产手机rem宽度超过实际宽度

  4. word文件命令行打印

  5. nodejs 长连接

  6. css3 文字渐变色

  7. nginx用域名来转发请求

  8. ios13 vpn 能连接但不能传数据问题解决

  9. jxa运动指令脚本

  10. 判断变量是否 0 或者 '0'

  11. npm设置仓库地址和代理

  12. 树莓派 3B/3B+ usb启动

  13. putty使用http代理连接服务器

  14. mysql导出csv文件

  15. sendmail用nginx做代理

  16. mysql选取内容导出到文件

  17. 简易版事件封装

  18. 随机取某个概率区间的代码

畅言模块加载中