我简化了以下服务代码,以便在此处发布
Load(Channel: any) {
//
let URL = Globals.AppSiteRoot + Channel.URL
return this.LoadData(URL)
}
Load_Default() {
let URL = Globals.AppSiteRoot + "dir1/somedata.XML"
console.log("XYZService.Load_Default------.------>>URL", URL)
//
return this.LoadData(URL)
.then(data => {
{
// do some processing here
console.log("XYZService.Load_Default<<P------.------data", data)
console.log("XYZService.Load_Default<<P------.------This.Data", this.Data)
}
});
}
// https://medium.com/@balramchavan/using-async-await-feature-in-angular-587dd56fdc77
// https://v5.angular.io/api
// https://v5.angular.io/guide/comparing-observables
LoadData(URL: string) { // : Observable<any>
return new Promise(resolve => {
// first argument is URL, put config as second argument
// return this.http.get(URL, {responseType: 'text'})
this.HttpClient.get(URL)
.map(res => res)
.subscribe(
data => {
//
console.log("XYZService.LoadData<<P------.------http.get=>data", data)
// Do some processing here, if needed...
this.Data = data
// return new Observable(this.Data);
resolve(this.Data)
}
,
err => {
// https://forum.ionicframework.com/t/handle-errors-with-http-services/53229
console.log("XYZService.LoadData<<P------.------http:ERR", err)
}
);
});
}
在XYZ组件中,请执行以下操作:
Show(Channel: any) {
console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
//
this.XYZService.Load(Channel)
.then(data => {
console.log("XYZComponent.Show------.------>>data", data)
this.NavController.parent.select(1);
});
}
如果我转为使用 async / await ,则我的组件代码将变成这样,我必须承认,一旦接受await被阻塞,该代码似乎比使用Promise .then更干净。 ..
async ShowV2(Channel: any) {
console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
//
const data = await this.XYZService.Load(Channel)
console.log("XYZComponent------.------>>data", data)
//
this.NavController.parent.select(1)
}
我从阅读的许多帖子和博客中得到的信息都是混杂的。
有人说如果您希望只接收一次数据,请不要使用HttpClient.get.subscribe ...,而是使用.toPromise(),但是它们从不显示如何处理错误。
有人说async / await只是仍然在后台使用Promises的Sugar语法。
有人说Observable更好,甚至Angular也广泛使用它们。
关于.Load().Load_Default()和组件.Show()方法中的代码,这些地方都可以期待Observables以及如何对其进行编码?
我已在其他地方使用ReplaySubject(1)广播服务中的事件并在页面之间进行间接通信。但是,我不确定这是另一个使用它的地方。
我对ReplaySubject(1)之类的事件发射器的典型关注,尤其是当我几个月后访问代码时,
1)我如何确保只订阅一次活动?在哪里?
2)我退订了吗?在哪里?
顺便说一句,即使我使用的是Promises,Observables,ReplaySubject(1),这对我来说都是中国人,也是我分心和沮丧的巨大来源,可以实现我的简单目标,即显示一些我从网络上检索到的数据或图片。 因此,如果您有一种方法/模式可以清楚地放下代码,以便当我从现在开始四个月复出时,一切都说得通:)
请包括您将在生产中使用的带有错误处理的模板代码。 感谢您分享您的见解。
npm show ionic version
5.4.16
npm show cordova version
9.0.0
npm show angular version
1.7.9
show @angular/core version
9.0.6
ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 9.0.4
Node: 10.16.0
OS: win32 x64
Angular: 5.0.3
... common, compiler, compiler-cli, core, forms, http
... platform-browser, platform-browser-dynamic
Ivy Workspace: Yes
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.900.4 (cli-only)
@angular-devkit/build-optimizer 0.0.35
@angular-devkit/core 9.0.4 (cli-only)
@angular-devkit/schematics 9.0.4 (cli-only)
@schematics/angular 9.0.4 (cli-only)
@schematics/update 0.900.4 (cli-only)
rxjs 5.5.2
typescript 2.8.3
webpack 3.12.0
答案 0 :(得分:2)
我建议使用Observables代替Promises,因为Angular首先使用了Observables,并且在某种程度上促进了反应式。
考虑以下示例代码:
@Injectable({
providedIn: 'root'
})
export class SomeService {
private readonly URL: string = 'someurl';
constructor(private http: HttpClient) {}
public loadData(): Observable<any> {
return this.http.get(this.URL).pipe(
// if you want to handle errors you can use the catchError operator
// however, a better way is to use a HTTP Interceptor instead
// if you want to see how you can handle errors with the interceptor let me
// know
catchError(error => throwError(error)),
map(res => // do some transformation if you need),
tap(res => // add some side effects if you need)
// don't subscribe in the service - it is considered to be a bad practice
}
}
您可以在组件中调用该方法并手动进行订阅,也可以使用模板中的async
管道自动进行订阅和取消订阅。
尽管取消可观察对象的订阅非常重要,以避免内存泄漏,但是Angular为HttpClient管理此操作,因此您无需手动取消订阅。
对于所有其他Observable,您可以使用take
,first
,last
,takeUntil
之类的运算符,或者将订阅存储在类型为Subscription
的属性中,然后在OnDestroy生命周期挂钩中取消订阅(对于takeUntil
运算符,必须在下一个调用并为参数Subject
完成/取消订阅的情况下执行相同操作)。
如果要改为使用Promises,可以使用trycatch
块来处理错误。
我创建了一个堆栈here,其中包含了错误拦截器。
确保像这样从应用程序模块在providers数组中提供拦截器:
providers: [{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }],