- Date
09/07 2016
https://github.com/nodejs/node/blob/master/lib/fs.js
同步 与 异步 用户JS代码样例:
// https://nodejs.org/api/fs.html
const fs = require('fs');
// ASYNC
fs.readFile('/etc/passwd', 'utf8', function (err, data){
if (err) throw err;
// File Content
var content = data;
console.log(content);
});
// SYNC
var content = fs.readFileSync('/etc/passwd', 'utf8');
console.log(content);
Node Lib 源码分析:
// binding 为 Node JS 项目的模块管理系统,代表 和 `src/` 目录下面的 `C++` 代码函数绑定
const binding = process.binding('fs');
// ASYNC
fs.readFile = function(path, options, callback_) {
// 注: 删掉了不必要的代码
var context = new ReadFileContext(callback, encoding);
context.isUserFd = isFd(path); // file descriptor ownership
var req = new FSReqWrap();
req.context = context;
req.oncomplete = readFileAfterOpen;
if (context.isUserFd) {
process.nextTick(function() {
req.oncomplete(null, path);
});
return;
}
// 绑定了 C++ `src/node_file.cc <https://github.com/nodejs/node/blob/master/src/node_file.cc>`_
// 中的 `Open` 函数
binding.open(pathModule._makeLong(path),
stringToFlags(flag),
0o666,
req);
};
// SYNC
function tryReadSync(fd, isUserFd, buffer, pos, len) {
// 注: 删掉了不必要的代码
return fs.readSync(fd, buffer, pos, len);
}
fs.readSync = function(fd, buffer, offset, length, position) {
// 注: 删掉了不必要的代码
// 绑定了 C++ `src/node_file.cc <https://github.com/nodejs/node/blob/master/src/node_file.cc>`_
// 中的 `Read` 函数
var r = binding.read(fd, buffer, offset, length, position);
var str = (r > 0) ? buffer.toString(encoding, 0, r) : '';
return [str, r];
};
fs.readFileSync = function(path, options) {
// 注: 删掉了不必要的代码
var isUserFd = isFd(path); // file descriptor ownership
var fd = isUserFd ? path : fs.openSync(path, flag, 0o666);
var buffer = tryCreateBuffer(size, fd, isUserFd);
tryReadSync(fd, isUserFd, buffer, pos, size - pos);
return buffer;
};
现在简化JS代码:
// Sync
var r = binding.read(fd, buffer, offset, length, position);
// ASYNC
var ctx = new ReadFileContext(callback);
// https://github.com/nodejs/node/blob/master/lib/fs.js#L310
// ctx.read 方法为读取文件方法
// binding.read(this.fd, buffer, offset, length, -1, req); // 等价于同步模式
var req = new FSReqWrap(); // 绑定了 `C++` `src/node_file.cc` 当中的 `FSReqWrap` 类
req.context = ctx; // ctx.callback
binding.open(fd, flags, mode, req);
// `req` 为 `C++` `src/node_file.cc` 当中的 `FSReqWrap` 类
// `req` 实例里面把 用户传递进去的 `callback` 绑定在 `req` 实例中的 `oncomplete` 方法上(通过它来触发)
TODO:
- C++ 代码分析
- libuv <https://github.com/nodejs/node/blob/master/deps/uv/src> 的封装