-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add .select() method #5
base: main
Are you sure you want to change the base?
Conversation
Furthermore, this does make the chainable methods more flexible. The chaining mechanism is basically overwriting some internal state on the class. So the user can chain things in any order and multiple times. The latest state wins. const loader = loader.service('users');
If (something) {
loader.multi('myKey')
} else {
loader.key('myKey')
}
If (somethingElse) {
loader.select(['name'])
}
await loader.load(1) But, we may want to lock this down...because the user can chain methods that don't make sense on some other methods. // .key('myKey') has no effect here
const users = loader.service('users').key('myKey').find() |
This looks good. I don't think the risks of chaining flexibility are material enough to merit writing code to keep users from accidentally doing something dumb. |
I wonder if we should move the // This can be set at the global level and at the service level.
// But you can currently also set it per method call too.
const myCacheParams = (params) => {
return {
...some custom params
}
}
const result = await loader.service('users').load(1, params, myCacheParams); There currently is not a way to override the const result = await loader.service('users')
// function as second arg?
.key('myKey', myCacheKeyFn)
// Same for multi
.multi('myKey', myCacheKeyFn)
// better name? Note it does not take a first arg. it gets params from the load()
.params(myCacheParamsFn)
// function as second arg?
.select(['name', 'email'], mySelectFn)
.load(1, params) |
I take most of that back actually. The But we could still do const result = await loader.service('users')
.key('myKey')
// better name? Note it does not take a first arg. it gets params from the load()
.params(myCacheParamsFn)
// function as second arg?
.select(['name', 'email'], mySelectFn)
.load(1, params) |
There may be some challenges introduced with this that relate to some of the more complicated set logic that @marshallswain may know about, too (can-connect). For example when loaded in a different order like const user2 = loader.service('users').select(['name']).load(1);
const user3 = loader.service('users').select(['role']).load(1);
const user1 = loader.service('users').load(1); I probably won't get any caching right? One thing that I see could improve performance here would be to always strip out the Another question is how frequently |
@daffl You would still get caching with const user2 = loader.service('users').select(['name']).load(1);
const user3 = loader.service('users').select(['role']).load(1);
const user1 = loader.service('users').load(1); Because you did not use And I use the |
The |
@daffl I'm thinking more on removing |
This PR makes the chainable methods more extendable and includes a new method
select()
.The main goal of this PR is to offer better performance when the user is "shaping" results, which is done primarily through the
$select
keyword. When using thequery.$select
the different shaped results are stored in the cache according to their params.But, if the loader took over the select/shape of results, results could be cached more efficiently.
The loader uses the same select algorithm as
@feathersjs/adapter-commons
for its defaultselectFn
. And the user can now pass a new configuration optionselectFn
that will be used if the call has a.select()
. And theselect()
can be used on ALL methods.Note that this does not attempt to remove
query.$select
or alter the cache key in any way. You should not useselect()
andquery.$select
in conjunction.You can also pass a
selectFn
argument to the configs. This is a sync function that is called for each result likeselect(selection)
. For example:We should probably update the
selectFn
to handle a promise. This would allow the method to handle basically any kind of "shaping" of results after the cache. It can also help decoupled nested loaders from this loader's cache. If the developer handled nested loaders in the genericselect()
method instead of the nested service hooks, when the nested loader is cleared the developer doesn't have to know to clear this loader too.Perhaps
select()
is not a great name for the method at that point either.