我需要/希望在forkJoin中使用六个以上的参数。目前,根据另一个related question的答案,似乎无法向forkJoin发送超过6个参数。
但是,基于官方文档,它说“forkJoin是一个运算符,它接受任意数量的Observable,它们既可以作为数组传递,也可以作为参数直接传递。”
forkJoin - 官方文档
好吧,我正在这样做,我收到一个错误TS2322:类型'foo'不能分配给'bar []'。
在我的研究中,我还发现如果你有一个返回不同类型的promises,最好不要将参数作为数组发送,因为它会将它们类型转换为相同的类型。 - Source
这是我的代码。我正在使用最新版本的Typescript和Angular 4。
ngOnInit() {
this.spinner.show();
Observable.forkJoin(
this.loadParams(), // Returns an Observable<Object>
this.service.getPromiseType1(), // The rest return Observable<Array>
this.service.getPromiseType2(),
this.service.getPromiseType3(),
this.service.getPromiseType4(),
this.service.getPromiseType5(),
this.service.getPromiseType6(),
).finally(() => this.spinner.hide())
.subscribe(
([param, promise1, promise2, promise3, promise4, promise5, promise6]) => {
this.job = job;
this.value1 = promise1;
this.value2 = promise2;
this.value3 = promise3;
this.value4 = promise4;
this.value5 = promise5;
this.value6 = promise6;
}, (error) => {errorHandlingFunction}
});
如果我删除任何单个参数,以便它将六个参数传递给forkJoin,它可以正常工作。所以我的问题是,在我的情况下,我想在一次调用中加载对象observable和后续数组observable,还有另一种方法吗?这是forkJoin的错误,因为官方文档说它应该能够接受任意数量的Observable?
我尝试创建一个Observable类型的数组,并在forkJoin中使用array.forEach(),但它抱怨返回类型为void。无论如何,这似乎是一种愚蠢的做法。
答案 0 :(得分:1)
正如answer在您链接的问题中解释的那样,参数的最大数量仅受类型定义的约束 - 而不是运行时源本身。类型定义很有用,因为它们声明了将为可观察流的下一步生成的数组元素类型(在您的情况下为[param, promise1, promise2, ...]
的类型)。
听起来,订阅处理程序中的作业的严格类型安全性是导致问题的原因。由于您有超过6个observable,它会将结果参数默认为共享类型,这可能与您尝试分配的字段类型不匹配。
有几种方法可以解决这个问题。您可以在订阅处理程序中转换参数,也可以自己添加自己的类型。转换参数是快速而肮脏的解决方案,但它会导致您失去类型安全性。自己添加类型可以让你保持类型安全,但也可能意味着你最终会得到任意数量的工厂方法声明。将以下内容放在项目中任何位置的类型定义文件(*.d.ts
)中。我喜欢将这样的类型定义放在同级别的typings/
目录中,放到我的app/
目录中。
import { Observable, SubscribableOrPromise } from 'rxjs/Observable';
declare module 'rxjs/observable/ForkJoinObservable' {
namespace ForkJoinObservable {
export function create<T, T2, T3, T4, T5, T6, T7>(v1: SubscribableOrPromise<T>, v2: SubscribableOrPromise<T2>, v3: SubscribableOrPromise<T3>, v4: SubscribableOrPromise<T4>, v5: SubscribableOrPromise<T5>, v6: SubscribableOrPromise<T6>, v7: SubscribableOrPromise<T7>): Observable<[T, T2, T3, T4, T5, T6, T7]>;
export function create<T, T2, T3, T4, T5, T6, T7, R>(v1: SubscribableOrPromise<T>, v2: SubscribableOrPromise<T2>, v3: SubscribableOrPromise<T3>, v4: SubscribableOrPromise<T4>, v5: SubscribableOrPromise<T5>, v6: SubscribableOrPromise<T6>, v7: SubscribableOrPromise<T7>, project: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7) => R): Observable<R>;
}
}
Declaration Merging的TypeScript文档页面中详细介绍了此过程。
编辑:看起来我使用旧版本的RxJS,结构发生了一些变化。以下内容应该更接近应该与当前结构一起使用的类型声明:
declare module 'rxjs/Observable' {
namespace Observable {
export function forkJoin<T, T2, T3, T4, T5, T6, T7>(sources: [ObservableInput<T>, ObservableInput<T2>, ObservableInput<T3>, ObservableInput<T4>, ObservableInput<T5>, ObservableInput<T6>, ObservableInput<T7>]): Observable<[T, T2, T3, T4, T5, T6, T7]>;
export function forkJoin<T, T2, T3, T4, T5, T6, T7>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>, v7: ObservableInput<T7>): Observable<[T, T2, T3, T4, T5, T6, T7]>;
}
}
我基于当前的forkJoin类型声明。
就模块扩充而言,上面的代码修改了绝对路径'rxjs/Observable'
定义的模块的类型声明。这与导入Observable
类时使用的导入路径相同。 RxJS定义的模块导出Observable
类及其字段。我们对该模块的扩充通过使用namespace
块来修改它。这允许我们在Observable
命名空间下添加类型声明(例如,Observable.myFunctionOrField
的类型声明),它看起来与调用静态函数相同。实际上,这声明了额外的Observable.forkJoin
函数可能性。
答案 1 :(得分:1)
感谢@MikeHill使我指向正确的方向。最终对我有用的解决方案是在angular-cli生成的src文件夹中添加types.d.ts。我相信您也可以在同一位置使用打字文件夹,但是您需要更新tsconfig.app.json文件,有关更多信息,请参阅本文。 https://github.com/angular/angular-cli/blob/6449a753641340d8fc19a752e1a1ced75f974efa/docs/documentation/1-x/stories/third-party-lib.md
用forkJoin输入7个参数的typings.d.ts
import { ObservableInput, Observable } from 'rxjs';
import { forkJoin } from 'rxjs/internal/observable/forkJoin';
declare module 'rxjs/internal/observable/forkJoin' {
export function forkJoin<T, T2, T3, T4, T5, T6, T7>(
sources: [
ObservableInput<T>,
ObservableInput<T2>,
ObservableInput<T3>,
ObservableInput<T4>,
ObservableInput<T5>,
ObservableInput<T6>,
ObservableInput<T7>
],
): Observable<[T, T2, T3, T4, T5, T6, T7]>;
export function forkJoin<T, T2, T3, T4, T5, T6, T7>(
v1: ObservableInput<T>,
v2: ObservableInput<T2>,
v3: ObservableInput<T3>,
v4: ObservableInput<T4>,
v5: ObservableInput<T5>,
v6: ObservableInput<T6>,
v7: ObservableInput<T7>,
): Observable<[T, T2, T3, T4, T5, T6, T7]>;
}
答案 2 :(得分:1)
叉子联接可以嵌套到六个或更少参数的逻辑组中。以下应该可以(但尚未经过测试):
ngOnInit() {
this.spinner.show();
Observable.forkJoin(
this.loadParams(),
Observable.forkJoin(
this.service.getPromiseType1(),
this.service.getPromiseType2(),
this.service.getPromiseType3(),
),
Observable.forkJoin(
this.service.getPromiseType4(),
this.service.getPromiseType5(),
this.service.getPromiseType6(),
)
)
.finally(() => this.spinner.hide())
.subscribe(payloads => {
[
this.job,
[
this.value1,
this.value2,
this.value3,
],
[
this.value4,
this.value5,
this.value6,
],
] = payloads
}, (error) => {
errorHandlingFunction
});
}
答案 3 :(得分:1)
从6.5版的rxJs开始,您可以使用值字典将任意数量的可观察对象放入forkJoin see the first example here
forkJoin({first: of(1), second: of(2), third: of(3)})
.subscribe(result => {console.log(result.first)});
答案 4 :(得分:0)
您确定6限制吗?
这个示例包含forkJoins中使用的10个Observable似乎可以正常工作
const oArray =
[ ... new Array(10).keys() ]
.map(n => Observable.of(n))
.reduce((obsArray, obs) => {
obsArray.push(obs);
return obsArray
}, new Array<Observable<number>>())
Observable
.forkJoin(oArray)
.subscribe(console.log, console.error, () => console.log('DONE'))
另外,我不了解您使用的finally
运算符。我在RxJs 5.5.2中没有它。