英文:
Angular Outside Subscribe Value Null
问题
我在一个项目中工作,基本上通过一个叫做 ServiceHandler 的中介类调用服务方法。在组件中,结果变量的控制台输出是 `undefined`。
有没有解决这个问题的方法?
**组件**
this.entityServiceHandler.saveEntityWithCondition(entity).subscribe(data => { this.result = data});
console.log(this.result);
**ServiceHandler**
public saveEntityWithCondition(entity): Observable<Entity>{
var subject = new Subject<any>();
this.subscriptions.push(
forkJoin({
conditionTrue: this.entityService.isConditionTrue(entity.property)
}).subscribe(({ conditionTrue }) => {
if (conditionTrue) {
this.entityService.save(entity).subscribe(
(response: Entity) => {
subject.next(response);
},
(errorResponse: HttpErrorResponse) => {
}
)
}
},
err => {},
() => {
}));
return subject.asObservable();
}
**服务**
public save(item: Entity) : Observable<Entity>{
public save(item: Entity): Observable<Entity> {
return this.httpClient.post<Entity>(`path`, item).pipe(catchError((err) => this.handleAndThrowError(err)));
}
}
英文:
I work on a project that basically calls service method via a mediate class which is called ServiceHandler. In the component the console output of the result variable is undefined
.
Is there any solution to solve this problem?
Component
this.entityServiceHandler.saveEntityWithCondition(entity).subscribe(data => { this.result = data});
console.log(this.result);
ServiceHandler
public saveEntityWithCondition(entity): Observable<Entity>{
var subject = new Subject<any>();
this.subscriptions.push(
forkJoin({
conditionTrue: this.entityService.isConditionTrue(entity.property)
}).subscribe(({ conditionTrue }) => {
if (conditionTrue) {
this.entityService.save(entity).subscribe(
(response: Entity) => {
subject.next(response);
},
(errorResponse: HttpErrorResponse) => {
}
)
}
},
err => {},
() => {
}));
return subject.asObservable();
}
Service
public save(item: Entity) : Observable<Entity>{
public save(item: Entity): Observable<Entity> {
return this.httpClient.post<Entity>(`path`, item).pipe(catchError((err) => this.handleAndThrowError(err)));
}
}
答案1
得分: 1
Welcome to StackOverflow. The reason why you see undefined
is that you are mixing synchronous and asynchronous code and this often leads to problems. Just move the console.log
inside the subscribe
and it should be OK.
// Kode asinkron - memerlukan waktu untuk menyelesaikan
this.entityServiceHandler.saveEntityWithCondition(entity).subscribe(data => {
this.result = data;
console.log(this.resul) // Ini akan ditampilkan
});
// Kode sinkron - terjadi segera setelah memanggil yang sebelumnya, tidak menunggu
// untuk menyelesaikannya. Ini berarti, hasilnya tidak terdefinisi
console.log(this.result);
EDIT:
Saya mengambil kebebasan dan menyederhanakan kode Anda sedikit. Anda melakukan banyak hal yang tidak perlu, seperti forkJoin
hanya untuk satu observable. Atau mendorong langganan ke dalam Array, kemungkinan untuk menutupnya nanti, tetapi tidak diperlukan ketika Anda menyusun ulang kode Anda sedikit.
import { filter, switchMap, catchError, EMPTY } from 'rxjs';
public saveEntityWithCondition(entity): Observable<Entity> {
// Tidak perlu forkJoin, cukup panggil fungsi dan salurkan
return this.entityService.isConditionTrue(entity.property).pipe(
// Ini memastikan bahwa conditionTrue memang benar
filter(conditionTrue => conditionTrue),
// Kemudian gunakan switchMap untuk memanggil layanan entitas dan melakukan penyimpanan
switchMap(() => this.entityService.save(entity)),
// Dan gunakan catchError untuk menangani masalah yang mungkin terjadi
catchError(error => {
// tangani kesalahan dengan cara tertentu - misalnya, log atau yang lain;
return EMPTY;
})
);
}
Anda tidak memerlukan subject
lagi karena Anda mengembalikan Observable<Entity>
langsung.
Anda juga tidak perlu mendorong Subscription
ke dalam array, karena berkat HttpClient yang Anda gunakan dan operator switchMap
yang disertakan, itu akan menangani unsubcribe
secara otomatis, ketika save
selesai.
英文:
welcome to StackOverflow. The reason why you see undefined
is that you are mixing synchronous and asynchronous code and this often leads to problems. Just move the console.log
inside the subscribe
and it should be OK.
// Asynchronous code - takes some time to finalize
this.entityServiceHandler.saveEntityWithCondition(entity).subscribe(data => {
this.result = data;
console.log(this.resul) // This'll be shown
});
// Synchronous code - happens just after calling previous, doesn't wait for it
// to finish. This means, result is undefined
console.log(this.result);
EDIT:
I took a liberty and simplified your code a bit. You are doing lots of unnecessary things, like forkJoin
for just one observable. Or pushing a subscription to an Array, likely to close it later, but it's not needed when you refcator your code a bit.
import { filter, switchMap, catchError, EMPTY } from 'rxjs';
public saveEntityWithCondition(entity): Observable<Entity> {
// No need to forkJoin, just call the function and pipe it
return this.entityService.isConditionTrue(entity.property).pipe(
// This makes sure that conditionTrue is true indeed
filter(conditionTrue => conditionTrue),
// Then use switchMap to call the entity service and perform save
switchMap(() => this.entityService.save(entity)),
// And use catchError to handle possible issues
catchError(error => {
// handle error in some way - i.e. log it or something;
return EMPTY;
})
);
}
You don't need subject
anymore because you are returning the Observable<Entity>
directly.
You also don't need to push the Subscription
to an array, because thanks to the HttpClient you are using and the switchMap
operator included, it will handle unsubcribe
automatically, when save
is finished.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论