私はこの質問について私自身の意見を持っていますが、確認して確認することをお勧めします。注意を払い、手伝ってくれてありがとう。ここにあります:ngRx状態の更新とエフェクトの実行順序
いくつかの状態の変更をトリガーするアクションと、いくつかのエフェクトが添付されているとします。だから私たちのコードは2つのことを行う必要があります - 状態を変えて、いくつかの副作用をします。しかし、これらのタスクの順序は何ですか?私たちはそれを同期してやっていますか?私は最初に状態を変えて副作用をすると信じていますが、この2つのタスクの間に何か他のことが起こる可能性はありますか?このように、状態を変更してから、以前に行ったHTTPリクエストに対して何らかの応答を得て、それを処理してから、副作用を行います。
[編集:]私はここにいくつかのコードを追加することにしました。また、私はそれをたくさん簡略化しました。
州:
export interface ApplicationState {
loadingItemId: string;
items: {[itemId: string]: ItemModel}
}
アクション:
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) {}
}
リデューサー:
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;
}
}
効果:
@Effect()
FetchItemAction$: Observable<Action> = this.actions$
.ofType('FETCH_ITEM')
.switchMap((action: FetchItemAction) => this.httpService.fetchItem(action.payload))
.map((item: ItemModel) => new FetchItemSuccessAction(item));
そして、これは我々がFetchItemAction発送方法です:
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])
}
}
理想のシナリオ:
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.
悪いシナリオ:
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
悪いシナリオが実際に起こるかできるのであれば問題は単純であるがない?
返信いただきありがとうございます!はい、私が言及した最後のシナリオは非常に望ましくないです –
しかし、あなたはどのようにその効果をもたらしましたか? setTimeout()を追加しましたか? 私の使用シナリオは次のとおりです: 1.ユーザーがアイテムをクリック 2.このアイテムのIDであるペイロードを持つアクションAをディスパッチします 3.一部のレデューサーは、このアイテムIDをロード状態(state.loading。 id) 4.このid(私たちはアクションをサブスクライブし、switchMapを実行します)でhttpリクエストを行います。 5.応答とディスパッチアクションA_complete を受け取ります。6.受け取ったアイテムを次のような状態に保存します。これは:state.items [state.loading.id] =レスポンスと同様にstate.loading.id = nullを実行します。 –
私が見る唯一の問題は、state.loading.idを変更する可能性がありますが、別の要求をしてください。この場合私たちの状態で最後のIDは私たちの前の項目になります –