如何 return 订阅中的 Observable?
How to return an Observable inside a subscription?
编辑:参见 Kurt Hamilton 的解决方案答案。
我正在调用一个 API 到 return settings.service.ts 中某些设置的值。
在 settings.component.ts 中,这些需要 returned 来填写表格 - 当 API 调用尚未完成时它会显示正在加载。
它正在与 'return of(fakeData)' 一起工作。但是,我不知道如何 return 'realData'。
而不是 console.log(realData) 我想要 return 而不是 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);
})
);
}
使用 concatMap
或 switchMap
到 运行 一个新的可观察对象(在你的例子中是 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')
}))
);
}
}
编辑:参见 Kurt Hamilton 的解决方案答案。
我正在调用一个 API 到 return settings.service.ts 中某些设置的值。 在 settings.component.ts 中,这些需要 returned 来填写表格 - 当 API 调用尚未完成时它会显示正在加载。
它正在与 'return of(fakeData)' 一起工作。但是,我不知道如何 return 'realData'。
而不是 console.log(realData) 我想要 return 而不是 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);
})
);
}
使用 concatMap
或 switchMap
到 运行 一个新的可观察对象(在你的例子中是 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')
}))
);
}
}