代码之家  ›  专栏  ›  技术社区  ›  Simm28

解决6个以上的forkJoin参数?

  •  8
  • Simm28  · 技术社区  · 8 年前

    我需要/希望在forkJoin中使用六个以上的参数。目前,根据另一个问题的答案 related question 似乎无法向forkJoin发送6个以上的参数。

    然而,根据官方文档,它说“forkJoin是一个操作符,它接受任意数量的可观察对象,这些对象可以作为数组传递,也可以直接作为参数传递。”

    forkJoin -官方文件

    好吧,我正在这样做,我得到一个错误TS2322:“foo”类型不可分配给“bar[]”类型。

    在我的研究中,我还发现,如果有返回不同类型的承诺,最好不要将参数作为数组发送,因为这会将它们转换为所有相同的类型- 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,那么它就可以正常工作。所以我的问题是,在我的情况下,我想在一个调用中加载可观察的对象和随后的数组,是否有其他方法可以做到这一点?这是forkJoin的一个bug吗?因为官方文档说它应该能够接受任意数量的可观测数据?

    我尝试创建一个类型为Observable的数组,并使用Array。forkJoin中的forEach(),但它抱怨返回类型void。不管怎么说,这似乎是一种简陋的方式。

    5 回复  |  直到 8 年前
        1
  •  7
  •   Mike Hill    7 年前

    作为 answer 解释在您链接的问题中,参数的最大数量仅受类型定义的约束,而不受运行时源本身的约束。类型定义很有用,因为它们声明了将为可观察流的下一步生成的数组元素类型(类型 [param, promise1, promise2, ...] 在您的情况下)。

    这听起来像是订阅处理程序中分配的严格类型安全是导致问题的原因。由于您有6个以上的可观察对象,因此它将结果参数默认为共享类型,该类型可能与您尝试分配的字段类型不匹配。

    有几种方法可以解决这个问题。您可以在订阅处理程序中强制转换参数,也可以自己添加自己的类型。强制转换参数是快速而肮脏的解决方案,但它会导致您失去类型安全性。自己添加类型可以维护类型安全,但也可能意味着您最终会得到任意数量的工厂方法声明。将下面的放置在类型定义文件中( *.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>;
        }
    }
    

    有关此过程的详细说明,请参见的TypeScript文档页 Declaration Merging


    编辑:看起来我使用的是旧版本的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定义的模块导出 可观察到 类及其字段。我们对该模块的扩充通过使用 namespace 块这允许我们在 可观察到 命名空间(例如,类型声明 Observable.myFunctionOrField )这看起来与对其调用静态函数相同。实际上,这声明了 Observable.forkJoin 功能可能性。

        2
  •  5
  •   JoAMoS    7 年前

    感谢@MikeHill为我指明了正确的方向。最终对我有效的解决方案是添加一个打字机。d、 ts到angular cli生成的src文件夹。我相信您也可以在同一位置使用typings文件夹,但您需要更新您的tsconfig。应用程序。json文件,有关更多信息,请参阅本文。 https://github.com/angular/angular-cli/blob/6449a753641340d8fc19a752e1a1ced75f974efa/docs/documentation/1-x/stories/third-party-lib.md

    打字。d、 使用forkJoin的7个参数的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]>;
    }
    
        3
  •  4
  •   Andrey Romanenko    6 年前

    从rxJs的6.5版开始,您可以使用值字典在forkJoin中放置任意数量的可观察对象 see the first example here

        forkJoin({first: of(1), second: of(2), third: of(3)})
                 .subscribe(result => {console.log(result.first)});
    
        4
  •  3
  •   André C. Andersen    7 年前

    Fork连接可以嵌套到包含六个或更少参数的逻辑组中。以下各项应能正常工作(但尚未测试):

    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
        });
    }
    
        5
  •  0
  •   Picci    8 年前

    你确定6的限制吗?

    这个例子在forkJoins中使用了10个可观察对象,看起来很有效

    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中没有它

    推荐文章