-
Notifications
You must be signed in to change notification settings - Fork 346
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
Question: Does transaction combine actions to multiple stores? #54
Comments
@transaction only optimized updates on the same store. So for example, if you call the following code: @transaction
method() {
this.storeOne.setActive(1);
this.storeOne.add({ name: 'qwe' });
} Subscribers to the store will get one notification instead twice (one for each call update). If it answers your question, please close the issue. Thanks. |
Hi @NetanelBasal. Thanks for the great framework! Do you consider adding this in a future release? The use case I'm thinking of is when you have 2 related entities, say Movie and Actor, where Movie has a field actorIds. There is a selector that returns the Actors of the "active" Movie. This goes well when you first add the Actors entities and then sets the active Movie. When you do it the other way around though things fall apart. So there is a workaround, but it would be handy to do these changes in an atomic way. |
Thanks, can you add a concrete example (stackblitz) so we can look into this? |
Here's an example: https://stackblitz.com/edit/angular-rqbnpv. Have a look at ActorQuery's selectActorNames() (see below) which combines the Actor and Movies store. Depending on whether we first add the Actors and call the MovieStore.setActive() method afterwards or vice versa, the selectActorNames() method succeeds or fails. This is because when we first call the setActive() method, the selector is immediately triggered, and at that time we don't find the corresponding Actors. Ideally the selectors should only be triggered after each 'tick'/event? I dunno. Or otherwise use the transaction mechanism for this? actor.query.ts
movie.service.ts
|
As I mentioned in my article, you should use the selectActorNames(): Observable<Actor[]> {
return combineLatest(this.movieQuery.selectActive(), this.selectAll({asObject: true})).pipe(
auditTime(0),
filter(([movie, actors]) => !!movie && !!actors),
map(([movie, actors]: [Movie, any]) => {
return movie.actorIds.map(actorId => actors[actorId].name)
})
);
} |
@david-bulte I'm working a prototype that improves the transaction API. First, a new operator: getMovies() {
return timer(1000).pipe(
mapTo(movies),
withTransaction(response => {
this.actorsStore.set(response.entities.actors);
this.genresStore.set(response.entities.genres);
const movies = {
entities: response.entities.movies,
ids: response.result
};
this.moviesStore.set(movies);
})
);
} The second is a built-in solution for the case you mentioned, something like: selectActorNames(): Observable<Actor[]> {
return combineLatest(this.movieQuery.selectActive(), this.selectAll({asObject: true})).pipe(
batch(),<====
filter(([movie, actors]) => !!movie && !!actors),
map(([movie, actors]: [Movie, any]) => {
return movie.actorIds.map(actorId => actors[actorId].name)
})
);
} |
@david-bulte check the new functionality here: https://stackblitz.com/edit/angular-brebji?file=src%2Fapp%2Factor.query.ts It's still experimental so let me know if there any issues. |
Thanks. This is working fine. Some more thoughts, some may be relevant, others probably out of scope:
|
Transactions are only for synchronous operations; we can't know that all the async operations are done. (unless we use zone js and we don't want to)
The |
If you have a nice suggestion for a solution to your first issue, share with us. |
I would say transactions are not necessary over async operations. This can be achieved by waiting for both operations to complete and then manipulate the store. But manipulating multiple stores so observables only fire once is very important in order to avoid ripple-effects. Otherwise, every selector spanning multiple stores has to use the auditTime operator. Not sure, but I can imagine that this also might add problems (values from single store access are rendered and next tick the things from multiple stores force a re-rendering. I don't have a stackblitz and just came over this question because we're currently choosing a state mgmt solution (competitors are NGXS and NgRx). |
I'm submitting a...
Question
This issue is just a question / potential request for clarifications in the docs.
The documentation provides examples where the transaction is applied to the methods in the same store. I poked around the code for
@transaction
, but could not quite understand how it works. The question is whether it can be applied to actions in different stores. For example:Thanks for the awesome library.
The text was updated successfully, but these errors were encountered: