Angular HttpClient:如果 get() 失败,则执行 post()
Angular HttpClient: If get() fails, then execute a post()
我将 HttpClient 注入到服务中。我设置了一个 BehaviorSubject 来跟踪对该值的更改。我是 运行 一个带有 json-server 的模拟数据库。当我给它一些存在的东西时,我的服务能够正确执行 get(),但是如果我给它一些不存在的东西,它会给出 404。我希望它执行 post()。
对于现实世界的解释:用户有一个日历,其中包含每一天的每日日志。如果他们 select 一天存在日志,它将 get() 它。但是如果他们 select 一天不存在,则该服务应该 post() 服务器上的一个空白。回到那天会得到()之前创建的空白
这是我目前拥有的:
getCurrentDay(id: string) {
this.http.get<DailyLog>(this.daysUrl + "/" + id).subscribe(data => {
this._currentDailyLog.next(Object.assign({}, data));
},
error => {
return console.log('Could not load daily log');
}
)
}
对于未来的搜索者,这是我在@Poul Krujit 的帮助下得到的答案。我不得不根据他的建议更改两件事:post 的 url 不能像 get() 那样包含 /id 并且您需要将对象作为 [=25= 中的第二个参数]().
getCurrentDay(id: string) {
const url = `${this.daysUrl}/${id}`;
this.http.get<DailyLog>(url).pipe(
catchError(error =>
error.status === 404
? this.http.post<DailyLog>(this.daysUrl, { "id": id, })
: throwError(error)
)
).subscribe({
next: (data) => this._currentDailyLog.next({ ...data }),
error: (error) => console.log('Could not load daily log:', error)
});
}
根据经验,您不应在服务中订阅 Observable。这使得调用者无法访问数据(或错误)。您应该使用运算符和 return Observable 而不是订阅。
让我们重构您的服务
export class SomeService {
getCurrentDay(id: string) {
return this.http.get<DailyLog>(this.daysUrl + "/" + id)
.pipe(
/** catchError will be called if an exception is thrown
/* and it expects you to return another Observable
/* which is a great place to make another call
* I assume post method will return newly created instance
*/
catchError(err => this.http.post<DailyLog>(this.daysUrl + "/" + id)),
// also if you need to do some stuff within your service, you can use tap
tap(data => this._currentDailyLog.next(data))
);
}
}
上面的方法做的是尝试取回数据,如果出错会调用post
api和returnpost
的结果。另外,一路更新 BehaviorSubject
。
注意:由于服务不再订阅,该方法的调用者必须订阅才能使所有内容运行(Observables默认是惰性的,不执行直到订阅)
您可以使用 catchError
运算符:
getCurrentDay(id: string) {
const url = `${this.daysUrl}/${id}`;
this.http.get<DailyLog>(url).pipe(
catchError((error) => error.status === 404
? this.http.post<DailyLog>(url)
: throwError(error)
)
).subscribe({
next: (data) => this._currentDailyLog.next({ ...data })),
error: (error) => console.log('Could not load daily log:', error)
});
}
我将 HttpClient 注入到服务中。我设置了一个 BehaviorSubject 来跟踪对该值的更改。我是 运行 一个带有 json-server 的模拟数据库。当我给它一些存在的东西时,我的服务能够正确执行 get(),但是如果我给它一些不存在的东西,它会给出 404。我希望它执行 post()。
对于现实世界的解释:用户有一个日历,其中包含每一天的每日日志。如果他们 select 一天存在日志,它将 get() 它。但是如果他们 select 一天不存在,则该服务应该 post() 服务器上的一个空白。回到那天会得到()之前创建的空白
这是我目前拥有的:
getCurrentDay(id: string) {
this.http.get<DailyLog>(this.daysUrl + "/" + id).subscribe(data => {
this._currentDailyLog.next(Object.assign({}, data));
},
error => {
return console.log('Could not load daily log');
}
)
}
对于未来的搜索者,这是我在@Poul Krujit 的帮助下得到的答案。我不得不根据他的建议更改两件事:post 的 url 不能像 get() 那样包含 /id 并且您需要将对象作为 [=25= 中的第二个参数]().
getCurrentDay(id: string) {
const url = `${this.daysUrl}/${id}`;
this.http.get<DailyLog>(url).pipe(
catchError(error =>
error.status === 404
? this.http.post<DailyLog>(this.daysUrl, { "id": id, })
: throwError(error)
)
).subscribe({
next: (data) => this._currentDailyLog.next({ ...data }),
error: (error) => console.log('Could not load daily log:', error)
});
}
根据经验,您不应在服务中订阅 Observable。这使得调用者无法访问数据(或错误)。您应该使用运算符和 return Observable 而不是订阅。
让我们重构您的服务
export class SomeService {
getCurrentDay(id: string) {
return this.http.get<DailyLog>(this.daysUrl + "/" + id)
.pipe(
/** catchError will be called if an exception is thrown
/* and it expects you to return another Observable
/* which is a great place to make another call
* I assume post method will return newly created instance
*/
catchError(err => this.http.post<DailyLog>(this.daysUrl + "/" + id)),
// also if you need to do some stuff within your service, you can use tap
tap(data => this._currentDailyLog.next(data))
);
}
}
上面的方法做的是尝试取回数据,如果出错会调用post
api和returnpost
的结果。另外,一路更新 BehaviorSubject
。
注意:由于服务不再订阅,该方法的调用者必须订阅才能使所有内容运行(Observables默认是惰性的,不执行直到订阅)
您可以使用 catchError
运算符:
getCurrentDay(id: string) {
const url = `${this.daysUrl}/${id}`;
this.http.get<DailyLog>(url).pipe(
catchError((error) => error.status === 404
? this.http.post<DailyLog>(url)
: throwError(error)
)
).subscribe({
next: (data) => this._currentDailyLog.next({ ...data })),
error: (error) => console.log('Could not load daily log:', error)
});
}