尝试从#34;可观察的链中观察到错误"

时间:2018-06-08 20:50:12

标签: javascript angular functional-programming rxjs observable

好。我的Angular组件中有一些异步代码,运行正常。看起来像这样(简要):

export class SomeComponent {

    user: User;
    /* ... */
    email: string;
    /* ... */

    private someMethod(): void {
      /* some code here */
      this.userService1.getUsers().subscribe(users => {
        users.forEach(user => {
          if (user.email && user.email === this.email) {
             this.userService2.getUser(user.id).subscribe(foundUser => {
               let someFields;
               if (foundUser) {
                 someFields = (({ field1, field2 }) => ({ field1, field2 }))(foundUser); 
               }
               this.user = {...user, ...someFields};
             });
           }
         });
      });
      /*some code here */              
    }
 }

我跳过一些类型和名称变量有点尴尬(但很简单)因为它不是重点。代码有效。但 我想封装用户构建的进程 (来自2个服务),因为我需要在不同的组件中使用它。我试过了,但是......

constructUser(email): Observable<IUser> {
  let finalUser: IUser;

  return this.userService1.getUsers().merge(users => {
    return users.filter(user => {
      if (user.email && user.email === email) {
        return this.userService2.getUser(user.id).map(foundUser => {
          let someFields;
          if (foundUser) {
            someFields = (({ field1, field2 }) => ({ field1, field2 }))(foundUser); 
          }
          finalUser =  {...user, ...someFields};

          return Observable.of(finalUser);
        });
      }
    });
  });
}

我的WebStorm没有显示任何错误。但是在控制台中我得到了 this.userService1.getUsers(...)。merge不是一个函数

我已尝试合并 concat flatMap ,无论如何 - 但仍然没有成功。唯一的区别是我得到的错误。我对rxjs没有多少经验,所以我被卡住了。任何帮助或提示将不胜感激。

UPD。
解决了,但是7天(虽然赏金活跃),任何人仍然欢迎更简洁和功能性的解决方案:)

3 个答案:

答案 0 :(得分:5)

我觉得这样的事情就是你想要的:

RxJs 5:

import 'switchMap' from 'rxjs/add/operator/switchMap';
import 'map' from 'rxjs/add/operator/map';


this.userService1.getUsers()
    .map(users => users.find(userInList => userInList.email === "SomeEmail")) //Map the observable with users to a single user
    .switchMap(user => this.userService2.getUser(user.id)) //Map the observable by an other observable
    .subscribe(...doSomething with the result)

RxJs 6:

import {map, switchMap} from 'rxjs/operators';

this.userService1.getUsers().pipe(
    map(users => users.find(userInList => userInList.email === "SomeEmail")), //Map the observable with users to a single user
    switchMap(user => this.userService2.getUser(user.id)) //Map the observable by an other observable
).subscribe(...doSomething with the result)

答案 1 :(得分:0)

正确答案(跳过某些类型并更改变量的真实姓名):

非常感谢@Robin Dijkhof,他以正确的顺序给了我 rxjs运算符

public constructUser(email: string): Observable<User> {
  return this.userService1.getUsers().pipe(
    map(users => users.find(userInList => userInList.email === email)),
    switchMap(user => {
      return this.userService2.getUser(user.id).map(foundUser => {
        if (foundUser) {
          return {...user, ...(({ field1, field2 }) => ({ field1, field2 }))(foundUser)};
        } else {
          return {...user};
        }
      });
    })
  );
}

现在,我可以轻松地使用该方法通过电子邮件抓取构建的用户(可能稍后我会用id替换电子邮件),例如:

this.myHelperService.constructUser(email).subscribe(user => {...});

我认为可以使解决方案更加实用和简洁(也许解决方案必须更加强大)... 所以!欢迎任何人,额外的50个奖励积分仍在这里7天=)

答案 2 :(得分:-2)

我认为你应该在做其他任何事情之前订阅

this.userService1.getUsers().subscribe(users => {...