1

I'm trying to learn and understand Rxjs and ngrx/store

I have two api calls, the first one gets me an array of character names, the second one gets me the inventory of a character.

How do I run the second function through the array returned by the first one, using ngrx/store action/reducers/effects?

This are the service functions:

public getCharacterNames(): Observable<string[]> {
  return this._http.get(this._url + '/characters?access_token=' + this._key)
    .map((res: Response) => res.json())
    .catch((error: any) => Observable.throw(error.json().error || 'server error'));
}

public getCharactersInventory(characterName: string): Observable<Bag[]> {
  return this._http.get(this._url + '/characters/' + encodeURI(characterName) + '/inventory?access_token=' + this._key)
    .map((res: Response) => res.json())
    .catch((error: any) => {return Observable.throw(error.json().error || 'server error'); });
}

These are the actions:

public loadCharacters(): Action {
  return {
    type: Gw2Actions.LOAD_CHARACTERS
  };
}

public loadCharactersSuccess(characters: Character[]) {
  return {
    type: Gw2Actions.LOAD_CHARACTERS_SUCCESS,
    payload: characters
  };
}

This is the reducer:

  case Gw2Actions.LOAD_CHARACTERS_SUCCESS: {
    return action.payload;
  }

And this is the effect I tried using:

@Effect() private loadCharacters$: Observable<Action> = this._actions$
  .ofType(Gw2Actions.LOAD_CHARACTERS)
  .map((action) => action.payload)
  .switchMap(() => this._gw2Service.getCharacterNames())
  .map((characterNames) => {
      let characters = [];
      characterNames.forEach((characterName) => {
        let characterBags = this._gw2Service.getCharactersInventory(characterName)
          .subscribe((res) => res);
        characters.push({
          name: characterName,
          bags: characterBags
        });
      });
      return characters;
    }
  )
  .map((characters: Character[]) => this._gw2Actions.loadCharactersSuccess(characters));
4

1 回答 1

0

我建议将 Rxjs 和 ngstore 的两个挑战分开。以下是从角色名称解析库存的方法。希望您能够将其映射到您的 ngstore 效果中。

let charNames$ = Rx.Observable.of([{name: 'a'}, {name: 'b'}, {name: 'c'}]); //mock names
let getInventoryFromName = name => Rx.Observable.of({owner: name}).delay(1000); //mock inventory

let result$ = charNames$.switchMap(names => Rx.Observable.forkJoin(names.map(n => getInventoryFromName(n.name))));

result$.subscribe(res => console.log('got some inventory/user pairs: ', res));
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

于 2017-02-18T18:36:40.547 回答