经过仔细的思考,最终设置了两个核心的过程,包裹模块内容 和 编译文件结果。
包裹模块内容就是将字符串的文件结果包裹一下函数,专注于处理字符串结果,将普通文件的文本进行包裹。
编译文件结果这一步就是将代码结果编译成 node 能够直接识别的 js 而使得下一步沙盒环境进行执行,每次通过文件结果动态在内存进行编译,从而使得下一步 js 的执行。
同步还是异步?
这个问题其实困扰了很久。最大的问题就是里面涉及了部分异步加载的问题,按照传统前端的做法,这里一般都是使用 callback 或者 promise(async/await) 的方式,但这样就会带来一个很大的问题。
如果是 callback 的方式,那么意味着最终我的 require 可能得这样调用:
var r = require("nedo");
var moduleA = r("./moduleA");
var moduleB = r("./moduleB");function log(module) {
// 所有执行过程作为 callback
// 这里拿到 module 的结果
console.log(module);
}
moduleA(log); // 传入 callback,moduleA 加载结束执行回调
moduleB(log); // 传入 callback,moduleB 加载结束执行回调
这样就显得很愚蠢,即使改成 AMD 那样的 callback 调用也感觉是在开历史的倒车。
如果是 promise(async/await) 这样的异步方式,那么意味着最终我的 require 可能得这样调用:
var r = require("nedo");
var moduleA = r("./moduleA");moduleA.then(module => {
// 这里拿到 module 结果
});
(async function() {
var moduleB = await r("./moduleB");
// 这里拿到 module 的结果
})();
说实话这种方式也显得很愚蠢。不过中间我想了个方法,包裹函数时多包一层,包一个 IIFE 然后自执行一个 async 的 wrapper,不过这样的话 bootstrap 文件就必须还得手动包裹在 async 的函数中,子函数的问题解决了但是上层没有解决,不够完美。
其实后来仔细的思考了一下,造成这样的问题的原因究其根本是因为 request 是 async 的,这就导致了后续的代码必须以 async 的方式出现。如果我们想要从硬盘读取一个文件,那么我们可以使用 promise 包裹的 fs.readFile,当然我们也可以使用 fs.readFileSync 。前者的方法会让后续的所有调用都变成异步,而后者的代码还是同步,虽然性能很差但是完全符合直觉。
所以就必须找到一个 sync 的 request 的形式,才能让最终调用变的完美,最终的想法结果应该如下:
var r = require("nedo");
var moduleA = r("./moduleA");
// moduleA 结果var moduleB = r("https://baidu.com");
// moduleB 结果,同步阻塞
思考了半天不知道 sync 的 request 应该怎么写,后来只得求助万能的 npmjs,结果真的发现了一个 sync-request 的包,仔细研究了一下代码发现核心是借助了 sync-rpc 这个包,虽然这个包 github 只有 5 个 star,下载量也不大。但是感觉却是非常的厉害,能够将任何异步的代码转化为同步调用的形式,战略性 star,日后可能大有所为…









