Сохраните тип mutiple Observable <T>, используя объединяющий () от rxjs под Angular? - PullRequest
3 голосов
/ 22 мая 2019

Когда мой компонент загружается, мне нужно использовать две службы. Оба должны быть закончены, прежде чем имеет смысл продолжить. Порядок их завершения является случайным и не должен составляться последовательно. Настройка выполняется по схеме ниже.

const observables = [
  this.donkeyService.getDonkey(),
  this.monkeyService.getMonkey()
];

combineLatest(observables)
  .subscribe(([donkeyResult, monkeyResult]) => {
    if (!!donkeyResult && !!monkeyResult) {
      ...
    }
  }

Мы заметили, что результаты не напечатаны, как ожидалось. Прошло некоторое время, прежде чем мы осознали это, но тип donkeyResult не Donkey , несмотря на определение сервера ниже!

getDonkey() : Observable<Donkey> { ... }

Наконец, я понял, что когда элементы доставляются в принимающий массив, они теряют свою актуальность, поскольку сам массив равен any [] . Таким образом, мы управляем этим с помощью литья следующим образом.

const observables = [
  this.donkeyService.getDonkey(),
  this.monkeyService.getMonkey()
];

combineLatest(observables)
  .subscribe(([_1, _2]) => {
    const donkeyResult = _1 as Donkey;
    const monkeyResult = _2 as Monkey;

    if (!!donkeyResult && !!monkeyResult) {
      ...
    }
  }

Я бы хотел провести рефакторинг кода, чтобы массив сохранил типы, указанные в сигнатурах методов сервиса, и не объединился в общий знаменатель любой .

Можно ли заставить TypeScript и / или Rxjs иметь массив, в котором первый элемент будет Donkey , а второй Monkey ? Могу ли я использовать структуру данных, отличную от массива?

Я попробовал (и, конечно, потерпел неудачу) несколько разных подходов, в том числе доработку путем приведения типов непосредственно в массив, вот так.

...
.subscribe(([_1 as Donkey, _2 as Monkey]) => { ... }

Есть ли аккуратный способ сохранить скучность? Мы открыты для изменения подхода друг к другу, так как мы владеем этой частью программного обеспечения и у нас есть дополнительное время, чтобы помассировать код.

Ответы [ 2 ]

3 голосов
/ 22 мая 2019

Перво-наперво, вы должны ввести свою функцию и ваш HTTP-вызов.

getMonkey(): Observable<Donkey> {
  return this.http.get<Donkey>(url);
}

После того, как вы это сделаете, вы должны ввести свой массив наблюдаемых:

const observables: [Monkey, Donkey] = [
  this.getMonkey(),
  this.getDonkey(),
];

Наконец, хотя и не обязательно, вы можете ввести параметры обратного вызова:

forkJoin(observables).subscribe(([monkey, donkey]: [Monkey, Donkey]) => {...});
1 голос
/ 22 мая 2019

Это звучит как сценарий использования для кортежей. https://visualstudiomagazine.com/articles/2016/02/01/type-safe-structures.aspx?m=1

type animalTuple = [Donkey, Monkey];
.subscribe(([donkeyResult, monkeyResult]: animalTuple) => { ... }
...