【问题标题】:Retain the type of mutiple Observable<T> using combineLatest() from rxjs under Angular?使用 rxjs 和 Angular 中的 combineLatest() 保留多个 Observable<T> 的类型?
【发布时间】:2019-10-08 13:15:20
【问题描述】:

当我的组件加载时,我需要使用两个服务。两者都需要在继续有意义之前完成。这些完成的顺序是随机的,不应该连续组成。设置遵循以下模式。

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]) => { ... }

有没有一种巧妙的方法来保持类型?我们对完全改变方法持开放态度,因为我们拥有这部分软件并有一些额外的时间来修改代码。

【问题讨论】:

  • 我想到的第一件事是将数组映射到另一个对象,例如map([donkey, monkey] =&gt; { return { donkey: donkey, monkey: monkey } as {donkey: Donkey, monkey: Monkey}; })。您仍然需要自己进行映射
  • 想知道您是否尝试过以下任一....subscribe(([(_1 as Donkey), (_2 as Monkey)]) =&gt; { ... } ...或....subscribe(([&lt;Donkey&gt;_1, &lt;Monkey&gt;_2]) =&gt; { ... }
  • 这是tuple 类型,.subscribe(([_1, _2]: [Donkey, Monkey]) =&gt; ...。不过,Combine latest 应该跟踪up to 6 类型的可观察对象,所以我猜问题是observables 的类型。
  • 添加到上述答案,combineLatest&lt;[Donkey, Monkey]&gt;&gt;(observables) .subscribe(([_1, _2]) =&gt; { const donkeyResult = _1; const monkeyResult = _2; if (!!donkeyResult &amp;&amp; !!monkeyResult) { ... } }

标签: angular typescript rxjs combinelatest


【解决方案1】:

首先,您必须键入函数和 HTTP 调用。

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

一旦完成,你必须输入你的 observables 数组:

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

最后,虽然没有必要,你可以输入你的回调参数:

forkJoin(observables).subscribe(([monkey, donkey]: [Monkey, Donkey]) => {...});

【讨论】:

  • 这是正确的。这也可以是一个替代方案:forkJoin&lt;[Monkey, Donkey]&gt;,如果未输入 observables。
  • 这适用于 forkJoin,它对它所连接的 observables 的元组类型是通用的,但不适用于 combineLatest,它对数组元素类型是通用的。特别是forkJoin&lt;Monkey, Donkey&gt;combineLatest&lt;Monkey | Donkey&gt;combineLatest&lt;any&gt;
  • combineLatest 之后的订阅或管道运算符中添加类型将起作用,但在这种情况下,这是必要的,而在 forkJoin 示例中则不需要,正如您所说。
【解决方案2】:

这听起来像是元组的用例。 https://visualstudiomagazine.com/articles/2016/02/01/type-safe-structures.aspx?m=1

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

【讨论】:

    猜你喜欢
    • 2021-04-28
    • 2021-03-06
    • 2017-12-29
    • 2021-02-21
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多