Return 到 lodash 链接中的父对象“_.chain()”
Return to parent object in lodash chaining "_.chain()"
我正在使用一个库 (lowdb),它在后台使用 lodash 在 json 文件中创建本地数据库。我想知道的是如何在修改子对象以修改另一个对象后到达 lodash 链接中的父对象,例如
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('db.json');
const db = low(adapter);
/*
Eg. DB structure:
{
"posts": [
{
"id": 1,
"title": "post1"
},
{
"id": 2,
"title": "post2"
},
{
"id": 3,
"title": "post3"
}
]
}
*/
db
.get('posts')
.find({ id: 2 })
.assign({ title: 'edited title' })
//after that I want to go back to posts to edit another one in the same chain
.write();
我知道它可以在多个调用中完成,但我想知道是否可以在一个链中完成。
简答
如果您的目标是使代码尽可能美观,我建议您使用 lodash-id 及其 updateById
函数。我在我的长篇回答中介绍了所有可能的解决方案,但我个人会避免直接链接,而是做类似的事情:
const lodashId = require('lodash-id');
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('db.json');
const db = low(adapter);
db._.mixin(lodashId);
const posts = db.get("posts");
posts.updateById( 1, { title: 'edited title 1' }).commit();
posts.updateById( 2, { title: 'edited title 2' }).commit();
posts.updateById( 3, { title: 'edited title 3' }).commit();
posts.write();
长答案
有几种方法可以解决这个问题,updateById
并不是目前唯一的方法。事实上,也可以通过使用 tap
函数在一个链中执行此操作。下面我介绍几种方案。
我可以在浏览器中快速试用这些功能吗?
当然可以!我实际上制作了一个 Codepen,您可以在其中直接在浏览器中尝试所有不同的可能方法,只需记得打开浏览器控制台查看测试结果!这是 link:
https://codepen.io/jhack_jos/pen/XWNrpqX
如何调用函数?
所有这些函数都接收一个适配器作为输入。你可以这样称呼他们:
const result = testcaseXY(adapter);
1A) 点击并查找+分配
function testcase1A(adapter)
{
const db = low(adapter);
return db
.get("posts")
.tap( (posts) => _.chain(posts).find({ id: 1 }).assign({ title: 'edited title 1' }).commit())
.tap( (posts) => _.chain(posts).find({ id: 2 }).assign({ title: 'edited title 2' }).commit())
.tap( (posts) => _.chain(posts).find({ id: 3 }).assign({ title: 'edited title 3' }).commit())
.write();
}
什么是 tap
?
- 它是 lodash
的效用函数
- 它不直接改变数据库
- 但是,它确实将对对象 hold 的引用传递给
interceptor
函数(在本例中我使用了箭头函数)
- 可以更改对值的引用,从而影响数据库中的对象
- 在数据库上调用
.write()
使更改确定。
2A) 点击并查找+设置
function testcase2A(adapter)
{
const db = low(adapter);
_.mixin(lodashId);
return db
.get("posts")
.tap( (posts) => _.chain(posts).find({ id: 1 }).set("title", 'edited title 1').commit())
.tap( (posts) => _.chain(posts).find({ id: 2 }).set("title", 'edited title 2').commit())
.tap( (posts) => _.chain(posts).find({ id: 3 }).set("title", 'edited title 3').commit())
.write();
}
什么是 set
?
- 这是一种比
.assign
更简单的方法,但只有一个 属性.
- 您可能期望
.set
比 .assign
更快
3A) 点击并更新 Id
function testcase3A(adapter)
{
const db = low(adapter);
_.mixin(lodashId);
return db
.get("posts")
.tap( (posts) => _.chain(posts).updateById( 1, { title: 'edited title 1' }).commit())
.tap( (posts) => _.chain(posts).updateById( 2, { title: 'edited title 2' }).commit())
.tap( (posts) => _.chain(posts).updateById( 3, { title: 'edited title 3' }).commit())
.write();
}
什么是 updateById
?
- 这是一个由lodash-id library
公开的函数
- 你必须先将它作为mixin添加到lowdb
- 要这样做,您首先需要使用
const lodashId = require('lodash-id')
来要求它
- 那么你需要调用
db._.mixin(lodashId)
;
- 这里我直接调用
_.mixin(lodashId)
,因为我直接在 tap
函数中使用 lodash,没有经过 lowdb
1B) 临时变量 & find+assign
function testcase1B(adapter)
{
const db = low(adapter);
const posts = db.get("posts");
posts.find({ id: 1 }).assign({ title: 'edited title 1' }).commit();
posts.find({ id: 2 }).assign({ title: 'edited title 2' }).commit();
posts.find({ id: 3 }).assign({ title: 'edited title 3' }).commit();
return posts.write();
}
如您所见,在这里使用临时变量可以使我们的代码更紧凑,更易于阅读、调试和重构。
2B) 临时变量 & find+set
function testcase2B(adapter)
{
const db = low(adapter);
const posts = db.get("posts");
posts.find({ id: 1 }).set("title", 'edited title 1').commit();
posts.find({ id: 2 }).set("title", 'edited title 2').commit();
posts.find({ id: 3 }).set("title", 'edited title 3').commit();
return posts.write();
}
3B) 临时变量 & updateById
function testcase3B(adapter)
{
const db = low(adapter);
db._.mixin(lodashId);
const posts = db.get("posts");
posts.updateById( 1, { title: 'edited title 1' }).commit();
posts.updateById( 2, { title: 'edited title 2' }).commit();
posts.updateById( 3, { title: 'edited title 3' }).commit();
return posts.write();
}
感谢阅读!
如果您需要,我很乐意提供任何进一步的解释。
作为奖励,我要补充的是,可以将一些聪明的实用函数编写为 lowdb/lodash 混合,以使我们能够拥有更短的语法并仍然正确地链接。然而,这可能比您要找的更多。
我正在使用一个库 (lowdb),它在后台使用 lodash 在 json 文件中创建本地数据库。我想知道的是如何在修改子对象以修改另一个对象后到达 lodash 链接中的父对象,例如
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('db.json');
const db = low(adapter);
/*
Eg. DB structure:
{
"posts": [
{
"id": 1,
"title": "post1"
},
{
"id": 2,
"title": "post2"
},
{
"id": 3,
"title": "post3"
}
]
}
*/
db
.get('posts')
.find({ id: 2 })
.assign({ title: 'edited title' })
//after that I want to go back to posts to edit another one in the same chain
.write();
我知道它可以在多个调用中完成,但我想知道是否可以在一个链中完成。
简答
如果您的目标是使代码尽可能美观,我建议您使用 lodash-id 及其 updateById
函数。我在我的长篇回答中介绍了所有可能的解决方案,但我个人会避免直接链接,而是做类似的事情:
const lodashId = require('lodash-id');
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('db.json');
const db = low(adapter);
db._.mixin(lodashId);
const posts = db.get("posts");
posts.updateById( 1, { title: 'edited title 1' }).commit();
posts.updateById( 2, { title: 'edited title 2' }).commit();
posts.updateById( 3, { title: 'edited title 3' }).commit();
posts.write();
长答案
有几种方法可以解决这个问题,updateById
并不是目前唯一的方法。事实上,也可以通过使用 tap
函数在一个链中执行此操作。下面我介绍几种方案。
我可以在浏览器中快速试用这些功能吗?
当然可以!我实际上制作了一个 Codepen,您可以在其中直接在浏览器中尝试所有不同的可能方法,只需记得打开浏览器控制台查看测试结果!这是 link: https://codepen.io/jhack_jos/pen/XWNrpqX
如何调用函数?
所有这些函数都接收一个适配器作为输入。你可以这样称呼他们:
const result = testcaseXY(adapter);
1A) 点击并查找+分配
function testcase1A(adapter)
{
const db = low(adapter);
return db
.get("posts")
.tap( (posts) => _.chain(posts).find({ id: 1 }).assign({ title: 'edited title 1' }).commit())
.tap( (posts) => _.chain(posts).find({ id: 2 }).assign({ title: 'edited title 2' }).commit())
.tap( (posts) => _.chain(posts).find({ id: 3 }).assign({ title: 'edited title 3' }).commit())
.write();
}
什么是 tap
?
- 它是 lodash 的效用函数
- 它不直接改变数据库
- 但是,它确实将对对象 hold 的引用传递给
interceptor
函数(在本例中我使用了箭头函数) - 可以更改对值的引用,从而影响数据库中的对象
- 在数据库上调用
.write()
使更改确定。
2A) 点击并查找+设置
function testcase2A(adapter)
{
const db = low(adapter);
_.mixin(lodashId);
return db
.get("posts")
.tap( (posts) => _.chain(posts).find({ id: 1 }).set("title", 'edited title 1').commit())
.tap( (posts) => _.chain(posts).find({ id: 2 }).set("title", 'edited title 2').commit())
.tap( (posts) => _.chain(posts).find({ id: 3 }).set("title", 'edited title 3').commit())
.write();
}
什么是 set
?
- 这是一种比
.assign
更简单的方法,但只有一个 属性. - 您可能期望
.set
比.assign
更快
3A) 点击并更新 Id
function testcase3A(adapter)
{
const db = low(adapter);
_.mixin(lodashId);
return db
.get("posts")
.tap( (posts) => _.chain(posts).updateById( 1, { title: 'edited title 1' }).commit())
.tap( (posts) => _.chain(posts).updateById( 2, { title: 'edited title 2' }).commit())
.tap( (posts) => _.chain(posts).updateById( 3, { title: 'edited title 3' }).commit())
.write();
}
什么是 updateById
?
- 这是一个由lodash-id library 公开的函数
- 你必须先将它作为mixin添加到lowdb
- 要这样做,您首先需要使用
const lodashId = require('lodash-id')
来要求它
- 那么你需要调用
db._.mixin(lodashId)
; - 这里我直接调用
_.mixin(lodashId)
,因为我直接在tap
函数中使用 lodash,没有经过 lowdb
1B) 临时变量 & find+assign
function testcase1B(adapter)
{
const db = low(adapter);
const posts = db.get("posts");
posts.find({ id: 1 }).assign({ title: 'edited title 1' }).commit();
posts.find({ id: 2 }).assign({ title: 'edited title 2' }).commit();
posts.find({ id: 3 }).assign({ title: 'edited title 3' }).commit();
return posts.write();
}
如您所见,在这里使用临时变量可以使我们的代码更紧凑,更易于阅读、调试和重构。
2B) 临时变量 & find+set
function testcase2B(adapter)
{
const db = low(adapter);
const posts = db.get("posts");
posts.find({ id: 1 }).set("title", 'edited title 1').commit();
posts.find({ id: 2 }).set("title", 'edited title 2').commit();
posts.find({ id: 3 }).set("title", 'edited title 3').commit();
return posts.write();
}
3B) 临时变量 & updateById
function testcase3B(adapter)
{
const db = low(adapter);
db._.mixin(lodashId);
const posts = db.get("posts");
posts.updateById( 1, { title: 'edited title 1' }).commit();
posts.updateById( 2, { title: 'edited title 2' }).commit();
posts.updateById( 3, { title: 'edited title 3' }).commit();
return posts.write();
}
感谢阅读!
如果您需要,我很乐意提供任何进一步的解释。 作为奖励,我要补充的是,可以将一些聪明的实用函数编写为 lowdb/lodash 混合,以使我们能够拥有更短的语法并仍然正确地链接。然而,这可能比您要找的更多。