Ich habe meine eigene Meinung zu dieser Frage, aber es ist besser zu überprüfen und sicher zu wissen. Danke, dass du aufpasst und versuchst zu helfen. Hier ist es:ngRx Zustand Update und Effekte Ausführungsreihenfolge
Stellen Sie sich vor, dass wir eine Aktion versenden, die einige Zustandsänderungen auslöst und auch einige Effekte hat. Also muss unser Code zwei Dinge tun - den Zustand ändern und einige Nebenwirkungen haben. Aber was ist die Reihenfolge dieser Aufgaben? Machen wir sie synchron? Ich glaube, dass wir zuerst den Zustand ändern und dann den Nebeneffekt tun, aber besteht die Möglichkeit, dass zwischen diesen beiden Aufgaben etwas anderes passiert? So: Wir ändern den Status, erhalten dann eine Antwort auf die HTTP-Anfrage, die wir vorher gemacht haben, und behandeln sie dann, dann machen wir die Nebenwirkungen.
[Bearbeiten:] Ich habe beschlossen, hier einen Code hinzuzufügen. Und ich habe es auch sehr vereinfacht.
Zustand:
export interface ApplicationState {
loadingItemId: string;
items: {[itemId: string]: ItemModel}
}
Aktionen:
export class FetchItemAction implements Action {
readonly type = 'FETCH_ITEM';
constructor(public payload: string) {}
}
export class FetchItemSuccessAction implements Action {
readonly type = 'FETCH_ITEM_SUCCESS';
constructor(public payload: ItemModel) {}
}
Reducer:
export function reducer(state: ApplicationState, action: any) {
const newState = _.cloneDeep(state);
switch(action.type) {
case 'FETCH_ITEM':
newState.loadingItemId = action.payload;
return newState;
case 'FETCH_ITEM_SUCCESS':
newState.items[newState.loadingItemId] = action.payload;
newState.loadingItemId = null;
return newState;
default:
return state;
}
}
Wirkung:
@Effect()
FetchItemAction$: Observable<Action> = this.actions$
.ofType('FETCH_ITEM')
.switchMap((action: FetchItemAction) => this.httpService.fetchItem(action.payload))
.map((item: ItemModel) => new FetchItemSuccessAction(item));
Und das ist, wie wir FetchItemAction Versand:
export class ItemComponent {
item$: Observable<ItemModel>;
itemId$: Observable<string>;
constructor(private route: ActivatedRoute,
private store: Store<ApplicationState>) {
this.itemId$ = this.route.params.map(params => params.itemId);
itemId$.subscribe(itemId => this.store.dispatch(new FetchItemAction(itemId)));
this.item$ = this.store.select(state => state.items)
.combineLatest(itemId$)
.map(([items, itemId]: [{[itemId: string]: ItemModel}]) => items[itemId])
}
}
Wunschszenario:
User clicks on itemUrl_1;
we store itemId_1 as loadingItemId;
make the request_1;
user clicks on itemUrl_2;
we store itemId_2 as loadingItemId;
switchMap operator in our effect cancells previous request_1 and makes request_2;
get the item_2 in response;
store it under key itemId_2 and make loadingItemId = null.
Bad Szenario:
User clicks on itemUrl_1;
we store itemId_1 as loadingItemId;
make the request_1;
user clicks on itemUrl_2;
we store itemId_2 as loadingItemId;
we receive the response_1 before we made the new request_2 but after loadingItemId changed;
we store the item_1 from the response_1 under the key itemId_2;
make loadingItemId = null;
only here our effect works and we make request_2;
get item_2 in the response_2;
try to store it under key null and get an error
Die Frage ist also einfach, wenn das schlechte Szenario tatsächlich passieren kann, oder nicht?
Danke für die Antwort! Ja, das letzte Szenario, das ich erwähnt habe, ist sehr unerwünscht. –
Aber wie hast du diesen Effekt gemacht? Hast du setTimeout() hinzugefügt oder was? Mein Anwendungsszenario ist wie folgt: 1. Benutzer klickt auf einen Artikel 2. Wir versenden eine Aktion A mit Payload als ID dieses Artikels 3. Einige Reducer speichern diese Artikel-ID im Ladezustand (state.loading). ID) 4. Wirkung eine HTTP-Anfrage mit dieser ID machen (wir abonnieren eine Aktion und tun eine switchMap) 5. Wir erhalten die Antwort-und Versandaktion A_complete 6. mit einigen Reduzierungen speichern wir das empfangene Element in den Zustand wie this: state.items [state.loading.id] = Antwort und auch state.loading.id = null –
Das einzige Problem hier sehe ich ist, dass wir die state.loading.id ändern können, aber die vorherige Antwort schneller erhalten als wir mach eine andere Anfrage. In diesem Fall in unserem Zustand unter der letzten ID wäre unser vorheriger Artikel –