【问题标题】:Converting Array.map + Promise.all to Observable将 Array.map + Promise.all 转换为 Observable
【发布时间】:2017-09-14 02:55:08
【问题描述】:

我有返回 Promises 的 Vanilla.js (TypeScript) HTTP 客户端,如下所示:

class Person {
    name: string;
    id: number;
    friendsIds: number[];
}

class MyClient {

    getPersonInfo(personId: number): Promise<Person> {

        return fetch( '/people/' + personId)
            .then( r => r.json() as Person );
    }
}

我的显示代码获取每个人的朋友的详细信息,如下所示:

refresh(): void {

    client.getPersonInfo( 123 )
        .then( (person: Person) => {

            // array-of-promises:
            let friendsDetailsPromises: Promise<Person>[] = person.friendsIds.map( friendId => client.getPersonInfo( friendId  ) );

            // promise-of-array:
            let friendsDetailsAll     : Promise<Person[]> = Promise.all( friendsDetailsPromises );

            return friendsDetailsAll;
        } )
        .then( (friendsDetails: Person[]) => {

            // (do stuff for each Person)
        } )
        .catch( reason => console.error( reason ) );
}

我正在尝试将其移至 Angular 2 的内置 HTTP 客户端,该客户端返回 Observable&lt;T&gt; 而不是 Promise&lt;T&gt;,到目前为止我有:

class MyClient {

    private http: HttpClient; 

    getPersonInfo(personId: number): Observable<Person> {

        return this.http.get<Person>( '/person/' + personId );
    }
}

refresh(): void {

    client.getPersonInfo( 123 )
        .flatMap( (person: Person) => {

            // ...now what?
        } )
        .subscribe(
            (friendsDetails: Person[]) => {

            // (do stuff for each Person)
            },
            err => console.error( err )
        )
    );
}

我被困在flatMap 内部我应该做的事情上。

我看到这个 QA 询问如何将 Promise.all 转换为 ObservablePromise.all behavior with RxJS Observables?),答案是使用 forkJoin,但也建议使用 flatMap 并链接到这个帖子(RxJS Promise Composition (passing data))但是这个问题和我的完全不一样。

【问题讨论】:

  • 试试return Observable.combineLatest(person.friendsIds.map( friendId =&gt; client.getPersonInfo( friendId ) )
  • @HarryNinh 如果我转而使用Subject 而不是为每个请求创建一个新的Observable,这将如何改变? (我假设 Angular 的 HTTP 客户端会为每个请求创建一个新的 Observable - 但这不会首先破坏它是“可观察的”这一点,因为它不会更新其状态吗?)
  • 抱歉,您在此处使用Subject 的方法不是很清楚。对我来说,ObservablePromiseHttp 中的用途非常相似,如果您可以拥有 Promise 的数组,那么是什么阻止您拥有 Observable 的数组?
  • @HarryNinh 我没有返回 Promise&lt;T&gt;[] - 我使用 Promise.all 将其转换为 Promise&lt;T[]&gt; 并返回了它。我在问 Promise.all 的 Observable 等价物是什么 - 如果有更好的 RxJS 惯用方法。
  • 是的,你没有,但是在这个过程中你已经创建了friendsDetailsPromises: Promise&lt;Person&gt;[],这是一个promise数组。同样在这里,Observable.combineLatest 用于将Observable 的数组组合成一个Observable&lt;T[]&gt;

标签: angular reactjs rxjs observable


【解决方案1】:

您可以使用Observable.forkJoin,它将等待所有子可观察对象完成(与 Promise.all 相同)。

我发现以下语法有效(可能不是最好的,等待建议

this.http.get('list.json').switchMap(res => {                   
  return Observable.forkJoin(res.map(item => this.http.get(item + '.json')));  
})

请参考此Plunker demo


抱歉,可能有点晚了,因为花了一些时间才找到关于 rxjs5 的新用法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多