【问题标题】:How to return an Observable inside a subscription?如何在订阅中返回 Observable?
【发布时间】:2020-03-04 10:57:13
【问题描述】:

编辑:请参阅 Kurt Hamilton 的解决方案。

我正在调用 API 以返回 settings.service.ts 中某些设置的值。 在 settings.component.ts 中,需要返回这些以填充表单 - 当 API 调用尚未完成时,它会显示加载。

它正在处理“(fakeData) 的返回”。但是,我不知道如何返回“realData”。

而不是 console.log(realData) 我想返回它而不是 fakeData。

一些帮助会很好,在此先感谢!

下面是代码的相关部分。

settings.service.ts:

export interface Settings {
  setting1: boolean;
  setting2: string;
}

const fakeData = {
  setting1: true,
  setting2: 'test'
};

@Injectable()
export class SettingsService {
  defaultSettings: DefaultSettings[];

  constructor(private apiService: ApiService) { }

  loadSettings(): Observable<Settings> {
    this.apiService.getDefaultSettings().subscribe( defaultSettings => {
      // defaultSettings is needed for when value1 or value2 is 'null'
      // not implemented yet, but therefore this nested subscription structure
      this.defaultSettings = defaultSettings;

      const value1 = this.apiService.getSpecificSetting('setting1');
      const value2 = this.apiService.getSpecificSetting('setting2');

      forkJoin([value1, value2]).subscribe( result => {
        const realData = {
          setting1: result[0],
          setting2: result[1],
        };

        console.log(realData);
        // return of(settingsFound); not possible here ...
      });
    });

    return of(fakeData);
  }
}

settings.component.ts

settings: Observable<Settings>;

ngOnInit() {
  this.settings = this.settingsService.loadSettings().pipe(
    tap(settings => {
      this.settingsForm.patchValue(settings);
    })
  );
}

【问题讨论】:

  • 考虑使用 toPromise 方法将 api 调用转换为 promise。然后,您可以等待呼叫并等待您想要返回的结果。
  • @schlonzo 为什么要将 observables 转换为 Promise? Observables 要强大得多。
  • @KurtHamilton 是的,你是对的。我误读了这个问题。我以为他想将数据作为数组返回,而不是可观察的。我的错。

标签: javascript angular typescript observable angular2-observables


【解决方案1】:

使用concatMapswitchMap 在另一个可观察对象之后运行新的可观察对象(在您的情况下为forkJoin)。

@Injectable()
export class SettingsService {
  defaultSettings: DefaultSettings[];

  constructor(private apiService: ApiService) { }

  loadSettings(): Observable<Settings> {
    return this.apiService.getDefaultSettings().pipe(
      // save default settings
      // this may not be required if you only need default settings for the forkJoin
      tap(defaultSettings => this.defaultSettings = defaultSettings),
      // now run the next observable
      concatMap(defaultSettings => {
        return forkJoin({
          setting1: this.apiService.getSpecificSetting('setting1'),
          setting2: this.apiService.getSpecificSetting('setting2')
        });
      }),
      // now map the result of the forkJoin to the value to want to return
      // map won't be required in this case, 
      // as the arg going into forkJoin matches the desired return structure
      // I left it in for completeness
      map(result => {
        const realData = {
          setting1: result.setting1,
          setting2: result.setting2,
        };

        console.log(realData);

        return realData;
      })
    );
  }
}

精简版

没有我的注释和多余的调用,完成的结果如下所示:

@Injectable()
export class SettingsService {
  constructor(private apiService: ApiService) { }

  loadSettings(): Observable<Settings> {
    return this.apiService.getDefaultSettings().pipe(
      concatMap(defaultSettings => forkJoin({
        setting1: this.apiService.getSpecificSetting('setting1'),
        setting2: this.apiService.getSpecificSetting('setting2')
      }))
    );
  }
}

【讨论】:

  • 像魅力一样工作,非常感谢!我的实现必须使用综合版本。
猜你喜欢
  • 2018-09-01
  • 2017-02-17
  • 1970-01-01
  • 2017-03-26
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多