0

を使用する Angular アプリで次の効果​​を作成しましたrxjsMyActions.myActionで、プロパティ (ID の配列) を含むオブジェクトを受け取り、IDidsごとに を介して HTTP リクエストを送信しthis.myApiService.getResourceますObservable<Resource>。次に、すべての結果を配列に収集し、配列を渡す別のアクションをディスパッチします。

  public loadResources$: Observable<MyAction> = this.actions$.pipe(
    ofType(MyActions.myAction),
    switchMap(({ ids }) => from(ids).pipe(
      mergeMap(id => this.myApiService.getResource(id)),
      toArray()
    )),
    map(resources) => MyActions.resourcesLoaded({ resources } )),
  );

上記のコードは仕事をしますが、リアクティブ演算子の 2 つのフローをネストすることを避けるべきかどうか、またそれを記述するためのより良い方法があるかどうか疑問に思います。

私が疑問に思う理由は、そのテストを書くのに問題があるからです。以下のテストを書きましたが、合格できません。

 it('should dispatch an resourcesLoaded action with the resources', () => {
      const ids = ['5f7c723832758b859bd8f866'];
      const resources = [{} as Resource];

      const values = {
        l: MyActions.loadResources({ ids }),
        t: ids[0],
        o: MyActions.resourcesLoaded({ resources })
      };

      actions =         hot('--l------------', values);
      const get$ =     cold('  -------t-----', values);
      const expected = cold('---------o-----', values);

      myApiService.getResource.withArgs(ids[0]).returns(get$);

      expect(myEffects.loadResources$).toBeObservable(expected);
    });

私が得るエラーは次のとおりです。

     Expected $.length = 0 to equal 1.
Expected $[0] = undefined to equal Object({ frame: 50, notification: Notification({ kind: 'N', value: { ....
Error: Expected $.length = 0 to equal 1.
Expected $[0] = undefined to equal Object({ frame: 50, notification: Notification({ kind: 'N', value: { ....
    at <Jasmine>
    at compare (http://localhost:9876/Users/jacopolanzoni/Documents/Development/myProject/node_modules/jasmine-marbles/index.js:91:1)
    at <Jasmine>
4

2 に答える 2

0

しかし、リアクティブ演算子の 2 つのフローをネストすることを避けるべきかどうか、またそれを記述するより良い方法があるかどうか疑問に思います

少なくともこの場合は、何を達成したいかによると思います。

of([1,2,3]).pipe(mergeAll(), switchMap(value => http.get(...)))

とは異なり

of([1,2,3]).pipe(switchMap(ids => from(ids).pipe(mergeMap(...))))

最初のシナリオでは、各内側のオブザーバブルは次の値 (最後の値を除く) によって破棄されるため、解決されるのは 3 つだけです。
2 番目のシナリオでは、それらすべてを処理します。これは、内部の観測可能オブジェクト (によって管理されている) の配列を分解するためですswtichMap。したがって、その内部観測可能オブジェクトを破棄する唯一の方法は、新しい外部値 (たとえば、ID の別の配列) の場合です。ソースによって放出されます)。

ネストが不要なケースは次のとおりです。

of([1,2,3])
  .pipe(
    // whenever you want to explode an array,
    // it does not matter which higher order operator you use
    // since the operation is **synchronous**
    // so, `mergeAll`, `concatAll`, `switchAll` should work the same
    mergeAll(),

    mergeAll(id => this.apiService.useId(id))
  )

// same as

of([1,2,3])
  .pipe(
    mergeMap(ids => from(ids).pipe(mergeMap(id => this.apiService.useId(id))))
  )

ご覧のとおり、この場合、switchMapは に置き換えられていmergeMapます。

于 2021-01-10T16:17:47.600 に答える