【问题标题】:subscribing to nested observables订阅嵌套的 observables
【发布时间】:2022-01-24 19:40:48
【问题描述】:

我正在创建一个需要执行几个步骤的可观察对象,每个步骤都依赖于前一个步骤 - 例如获取 ID,使用该 ID 获取用户,使用该用户获取文章。每个步骤都会调用数据库,而数据库又会返回自己的 observable。我真的不知道如何处理嵌套的可观察对象而不订阅它们,或者确保当外部可观察对象被订阅时,最终所有嵌套的可观察对象也被订阅。

例子:

newArticle(article: Article): Observable<any> {
   // db api returns an observable of requests
   return this.db.get(`select id from user_ids where name = ${article.name}`).pipe(map((id) => {
      return this.db.get(`select user from users where user_id = ${id}`).pipe(map((user) => {
         return this.db.put(`insert into articles(user_name, title, content) values (${user.name}, ${article.title}, ${article.content});
      }));
   }));
}

使用这个当前方法不起作用,当从newArticle 返回的 observable 被订阅时,似乎只有最外层的 observable 被订阅并执行。在处理嵌套的 observables 的方式上我是否缺少一些东西?我对 rxjs 比较陌生,很难完全掌握 observables。任何帮助将不胜感激。

【问题讨论】:

    标签: rxjs observable


    【解决方案1】:

    在 RxJS 中,避免嵌套订阅的解决方案是使用“Higher Order Mapping Operator”(switchMapmergeMapconcatMapexhaustMap)。这些运算符将为您订阅一个“内部可观察对象”并发出它的排放量。

    我不会在这里讨论这些运算符之间的区别,但switchMap 将适用于您的情况。

    您的示例代码非常接近;您基本上可以使用switchMap 而不是map

    function newArticle(article: Article) {
        return this.db.get(`select id from user_ids where name = ${article.name}`).pipe(
            switchMap(id => this.db.get(`select user from users where user_id = ${id}`)),
            switchMap(user => this.db.put(`insert into articles(user_name, title, content) values (${user.name}, ${article.title}, ${article.content}`))
        );
    }
    

    如果您为特定目的定义单独的函数,您可能会发现代码更容易理解:

    function getUserIdForArticle(article: Article): Observable<string> {
        return this.db.get(`select id from user_ids where name = ${article.name}`);
    }
    
    function getUser(id: string): Observable<User> {
        return this.db.get(`select user from users where user_id = ${id}`);
    }
    
    function storeArticle(user: User, article: Article): Observable<Article> {
        return this.db.put(`insert into articles(user_name, title, content) values (${user.name}, ${article.title}, ${article.content}`);
    }
    
    function newArticle(article: Article) {
        return getUserIdForArticle(article).pipe(
            switchMap(id => getUser(id)),
            switchMap(user => storeArticle(user, article))
        );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-10
      • 2018-12-20
      • 2021-05-10
      • 2020-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      相关资源
      最近更新 更多