本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
【若川视野 x 源码共读】第10期 | # configstore 存储点击了解本期详情一起参与。
configstore 可以实现 json 数据存取,并把数据写入 json 文件,实现数据本地化。那是如何实现的呢,一起看看 configstore 源码。
1. 总览
configstore 有
属性: size, all
方法: 构造函数, get,set,set all属性,has,delete,clear
2. 构造函数
id 就是文件名, defaults 是创建示例时的默认 json 数据,options 未配置选项。
constructor(id, defaults, options = {}) {
const pathPrefix = options.globalConfigPath ?
path.join(id, 'config.json') :
path.join('configstore', `${id}.json`);
this._path = options.configPath || path.join(configDirectory, pathPrefix);
if (defaults) {
this.all = {
...defaults,
...this.all
};
}
}
使用示例看一下结果,configDirectory 为当前电脑用户的目录的 .config 文件夹,pathPrefix 是自己的configstore/${id}.json
let obj = {
a: 'aaa',
b: 'bbb'
}
let cs = new Configstore('likeMap', obj)
这里只是展示一下效果,实际上是在 set 函数执行时创建的。
3.属性
3.1 all
get 相当于定义私有属性,就是读取文件的内容,返回解析完成的 JSON 对象。
get all() {
try {
return JSON.parse(fs.readFileSync(this._path, 'utf8'));
} catch (error) {
// Create directory if it doesn't exist
if (error.code === 'ENOENT') {
return {};
}
// Improve the message of permission errors
if (error.code === 'EACCES') {
error.message = `${error.message}\n${permissionError}\n`;
}
// Empty the file if it encounters invalid JSON
if (error.name === 'SyntaxError') {
writeFileAtomic.sync(this._path, '', writeFileOptions);
return {};
}
throw error;
}
}
3.2 size
就是 key 的长度。
get size() {
return Object.keys(this.all || {}).length;
}
4. 方法
4.1 get
利用 dot-prop 库进行快速取值
import dotProp from 'dot-prop';
get(key) {
return dotProp.get(this.all, key);
}
4.2 set
也是利用 dot-prop 库进行快速设置值
set(key, value) {
const config = this.all;
if (arguments.length === 1) {
for (const k of Object.keys(key)) {
dotProp.set(config, k, key[k]);
}
} else {
dotProp.set(config, key, value);
}
this.all = config;
}
4.3 set all属性
就是在创建文件夹,并把数据全部直接写入文件,如果之前有文件存在,则直接删除新建。
set all(value) {
try {
// Make sure the folder exists as it could have been deleted in the meantime
fs.mkdirSync(path.dirname(this._path), mkdirOptions);
writeFileAtomic.sync(this._path, JSON.stringify(value, undefined, '\t'), writeFileOptions);
} catch (error) {
// Improve the message of permission errors
if (error.code === 'EACCES') {
error.message = `${error.message}\n${permissionError}\n`;
}
throw error;
}
}
4.4 has
利用 dot-prop 库的 has 方法。
has(key) {
return dotProp.has(this.all, key);
}
4.5 delete
先读取,删除后再存储。
delete(key) {
const config = this.all;
dotProp.delete(config, key);
this.all = config;
}
4.6 clear
直接清空
clear() {
this.all = {};
}
5. 总结
- 利用 ES6 的 get, set 特性定义私有属性。
- 把读取值和修改值分别封装为函数,从文件中读取和修改文件中内容实现数据同步。
- 扩展文件读取库: graceful-fs,文件写入库: write-file-atomic 。