使用angular2中的可观察对象有条件地进行api调用

时间:2018-08-19 10:09:06

标签: angular observable

我知道这是一个基本的问题,但是来自angular1背景...这让我很烦恼,我无法找到最佳的选择。

所以,这是我的用例:

  1. 我想进行api调用以获取用户首选项。
  2. 如果上述api不返回首选项,请调用其他api以获得默认首选项。
  3. 一旦收到这两种信息,请调用一个不同的函数来根据偏好设置小部件。

这是我到目前为止尝试过的:

getUserPreference(){
    this._myservice.getUserPrefrence(username).subscribe(response => {
      this.rawData = response;
      if(!this.rawData.length){
         this._myservice.getDefaultPreference().subscribe(response1 => {
             this.newUser = true;
             this.rawData = response1;
         })
         this.callFinalFunction(this.rawData);
      }
      this.callFinalFunction(this.rawData);
    })
}

但是上面的代码似乎是新手,必须有一些更好的方法来做到这一点。 任何人都可以在这里帮助我。如果需要更多信息,请告诉我。

4 个答案:

答案 0 :(得分:1)

我认为这段代码没有什么问题,或者可以改善它,而不仅仅是在第二次调用中调用final函数的一个小错误。如果第一个api不返回首选项,则最终函数将被调用两次。

getUserPreference(){
    this._myservice.getUserPrefrence(username).subscribe(response => {
      this.rawData = response;
      if(!this.rawData.length){
         this._myservice.getDefaultPreference().subscribe(response1 => {
             this.newUser = true;
             this.rawData = response1;
         })
         //remove this
         this.callFinalFunction(this.rawData);
      }
      //this will be called twice if second api is already called
      this.callFinalFunction(this.rawData);
    })
}

或者,您可以尝试使用switchMapmergeMap运算符。通常,switchMap运算符是用于维护单个内部订阅的mergeMap的更安全默认值。

这使用RxJS 5.5+管道运算符:

import { switchMap } from 'rxjs/operators';
import { of } from 'rxjs';

getUserPreference() {
  const userPreference$ = this._myservice.getUserPrefrence(username).pipe(
    switchMap(response => {
      if(!response.length) {
        this.newUser = true;
        return this._myservice.getDefaultPreference()
      }
      return Observable.of(response);
    })
  );
  userPreference$.subscribe(response => {
    this.rawData = response;
    this.callFinalFunction(this.rawData);
  })
}

RxJS <5.5:

import 'rxjs/add/operator/switchMap';
import 'rxjs/add/observable/of';

getUserPreference() {
  const userPreference$ = this._myservice.getUserPrefrence(username)
  .switchMap(response => {
    if(!response.length) {
      this.newUser = true;
      return this._myservice.getDefaultPreference()
    }
    return Observable.of(response);
  });
  userPreference$.subscribe(response => {
    this.rawData = response;
    this.callFinalFunction(this.rawData);
  })
}

答案 1 :(得分:0)

已经有一段时间没有使用旧版本的rxjs了,所以我希望我不会忘记语法。

getUserPreference(){
this._myservice.getUserPrefrence(username).mergeMap(response=>{
   if(!response.length){
     this.newUser = true;
     return this._myservice.getDefaultPreference();
   }
   return Observable.of(response);

}).subscribe(response=>{
  this.rawData = response;
  this.callFinalFunction(this.rawData);
})

基本上,您只会订阅一次。如果没有首选项,您将收到defaultPreference响应,否则您将获得用户首选项。

别忘了导入mergeMap和Observable。很抱歉,我不记得旧的导入路径的含义在我目前使用的angular 6中,有一个不同的rxjs版本

答案 2 :(得分:0)

如果您使用的是RxJS 6,则可以处理以下代码

getUserPreference(){
this._myservice.getUserPrefrence(username)
   .pipe(
      switchMap(response=>{
         if(!response){
            return this._myservice.getDefaultPreference();
         }
         return of(response);
      }),
      map(response=> {
         // call the widget function
      })
   ).subscribe(output=>{
       // final output
   })

答案 3 :(得分:0)

您错过了反应式编程的要点。我在纯RxJS 6中创建了一个示例,以说明一种更好的方法。

class UserService {
  private _user: Subject<User> = new ReplaySubject(1);
  private _preferences: Subject<UserPreferences> = new ReplaySubject(1);

  public get user$(): Observable<User> {
    return this._user.asObservable();
  }

  public get preferences$(): Observable<UserPreferences> {
    return this._preferences.asObservable();
  }

  constructor(private backendService: BackendService) {
    this.user$.subscribe(user => {
      this.backendService
        .getUserPrefrences(user.name)
        .pipe(
        switchMap(preferences =>
          preferences ? of(preferences) :
            this.backendService.getDefaultUserPreferneces())
        ).subscribe(preferences =>
          this._preferences.next(preferences)
        );
    });
  }

  public login(username: string, password: string): Observable<User> {
    let login = this.backendService.login(username, password).pipe(share());
    login.subscribe(user => this._user.next(user));
    return login;
  }

  public logout() {
    let logout = this.backendService.logout().pipe(share());
    logout.subscribe(user => this._user.next(user));
    return logout;
  }
}

您可以从任何关心它们的组件中订阅user$preferences$的可观察对象,并监听更改。

userService.preferences$.subscribe(preferences => {
  console.log('current user preferences : ', preferences);
});

Full Example