Angular 中处理异步和可观察对象的问题
problems handling asynchronism and observables in Angular
在我的项目中,我需要根据一些日期(月和年)计算一些数据,所以一旦我在数组“this.etiquetasEjeX”中有了日期。我循环它们以像这样计算组件中的数据
ngOnInit() {
this.getGastadoRealizado();
console.log('GraficaComponent-ngOnInit()-this.gastadoRealizado: ',this.gastadoRealizado);
}
getGastadoRealizado(){
let valorAnterior:number=0;
let valorEnMesYAño:number=0;
for(let etiqueta of this.etiquetasEjeX){
this.dataService.getGastadoRealizadoEnMesYAño(
this.proyectoId,
getMonthNumber(etiqueta.slice(0,etiqueta.length-4)),+etiqueta.slice(-4),
this.acumular)
.pipe(
tap(item=>console.log(`GraficaComponent-ngOnInit()-getGastoRealizado() de ${etiqueta} :
${item}`))
)
.subscribe(
item=>{
valorEnMesYAño=item;
this.gastadoRealizado.push(valorAnterior+valorEnMesYAño);
valorAnterior+=valorEnMesYAño;
this.gastadoRealizadoAcumulado += valorEnMesYAño;
}
)
}
}
在我的服务中,我有调用服务器的方法
getGastadoRealizadoEnMesYAño(proyectoId: string, mes:number, año:number, acumular:
boolean):Observable<number>{
return this.http.get<number>
(`${this.urlProyecto}/proyectos/${proyectoId}/mes/${mes+1}/anio/${año}/acumular/${acumular}/gastado`)
.pipe(
catchError(this.handleError)
)
}
问题是在循环内,我使 http.get 请求 return 可观察对象并且我失去了控制
当我登录控制台时,我看到了这个
我按我需要的顺序查看我的日期,因此循环以相同的顺序遍历它们
但是当我记录响应时,顺序是另一个完全随机的
而且由于我需要按顺序遍历并计算值以在图表中显示它们,这不值得,而且我不知道如何离开这里
我试过 async/await 使用 promises 得到相同的结果
我更新了服务
async getGastadoRealizadoEnMesYAño(proyectoId: string, mes:number,
año:number, acumular: boolean){
return await this.http.get<number>
(`${this.urlProyecto}/proyectos/${proyectoId}/mes/${mes+1}/
anio/${año}/acumular/
${acumular}/gastado`).toPromise();
}
以及组件中的调用
async getGastadoRealizado(){
let valorAnterior:number=0;
let valorEnMesYAño:number=0;
for(let etiqueta of this.etiquetasEjeX){
this.dataService.getGastadoRealizadoEnMesYAño(
this.proyectoId,
getMonthNumber(etiqueta.slice(0,etiqueta.length4)),
+etiqueta.slice(-4),this.acumular)
.then(
item=>{
valorEnMesYAño=item;
this.gastadoRealizado.push(valorAnterior+valorEnMesYAño);
valorAnterior+=valorEnMesYAño;
this.gastadoRealizadoAcumulado += valorEnMesYAño;
}
)
}
}
但是我每次运行顺序都不一样
有什么想法吗?
谢谢
The issue is that inside the loop for I make http.get requests that return observables and I loose the control
每个异步调用可能需要不同的时间量,因此可能不会 return 以相同的顺序响应。
And since I need to go through and calculate the values in that order to show them in a graph, this is not worth it and I do not know how to get out of here. Any idea Please?
解决方法是:
1.Convert 请求数组到异步响应数组(可观察对象或承诺)
2.Wait 直到所有请求都得到解决并且所有响应都使用 forkJoin()
或 Promise.all()
收到
3.Process 所有回复。
getGastadoRealizado() {
// ...
const responses = this.etiquetasEjeX.map(etiqueta => { // Converted for loop to map
return this.dataService.getGastadoRealizadoEnMesYAño(
// ...
).pipe(tap(item => {
// ...
}))
})
forkJoin(responses).subscribe(items => {
items.forEach(item => {
//...
})
})
}
更新:
对于更新后的问题,如果您return 承诺服务,那么...
getGastadoRealizado() {
// ...
const responses = this.etiquetasEjeX.map(etiqueta => { // Converted for loop to map
return this.dataService.getGastadoRealizadoEnMesYAño(
// ...
)
})
Promise.all(responses).then(items => {
items.forEach(item => {
//...
})
})
}
在我的项目中,我需要根据一些日期(月和年)计算一些数据,所以一旦我在数组“this.etiquetasEjeX”中有了日期。我循环它们以像这样计算组件中的数据
ngOnInit() {
this.getGastadoRealizado();
console.log('GraficaComponent-ngOnInit()-this.gastadoRealizado: ',this.gastadoRealizado);
}
getGastadoRealizado(){
let valorAnterior:number=0;
let valorEnMesYAño:number=0;
for(let etiqueta of this.etiquetasEjeX){
this.dataService.getGastadoRealizadoEnMesYAño(
this.proyectoId,
getMonthNumber(etiqueta.slice(0,etiqueta.length-4)),+etiqueta.slice(-4),
this.acumular)
.pipe(
tap(item=>console.log(`GraficaComponent-ngOnInit()-getGastoRealizado() de ${etiqueta} :
${item}`))
)
.subscribe(
item=>{
valorEnMesYAño=item;
this.gastadoRealizado.push(valorAnterior+valorEnMesYAño);
valorAnterior+=valorEnMesYAño;
this.gastadoRealizadoAcumulado += valorEnMesYAño;
}
)
}
}
在我的服务中,我有调用服务器的方法
getGastadoRealizadoEnMesYAño(proyectoId: string, mes:number, año:number, acumular:
boolean):Observable<number>{
return this.http.get<number>
(`${this.urlProyecto}/proyectos/${proyectoId}/mes/${mes+1}/anio/${año}/acumular/${acumular}/gastado`)
.pipe(
catchError(this.handleError)
)
}
问题是在循环内,我使 http.get 请求 return 可观察对象并且我失去了控制
当我登录控制台时,我看到了这个
我按我需要的顺序查看我的日期,因此循环以相同的顺序遍历它们
但是当我记录响应时,顺序是另一个完全随机的
而且由于我需要按顺序遍历并计算值以在图表中显示它们,这不值得,而且我不知道如何离开这里
我试过 async/await 使用 promises 得到相同的结果
我更新了服务
async getGastadoRealizadoEnMesYAño(proyectoId: string, mes:number,
año:number, acumular: boolean){
return await this.http.get<number>
(`${this.urlProyecto}/proyectos/${proyectoId}/mes/${mes+1}/
anio/${año}/acumular/
${acumular}/gastado`).toPromise();
}
以及组件中的调用
async getGastadoRealizado(){
let valorAnterior:number=0;
let valorEnMesYAño:number=0;
for(let etiqueta of this.etiquetasEjeX){
this.dataService.getGastadoRealizadoEnMesYAño(
this.proyectoId,
getMonthNumber(etiqueta.slice(0,etiqueta.length4)),
+etiqueta.slice(-4),this.acumular)
.then(
item=>{
valorEnMesYAño=item;
this.gastadoRealizado.push(valorAnterior+valorEnMesYAño);
valorAnterior+=valorEnMesYAño;
this.gastadoRealizadoAcumulado += valorEnMesYAño;
}
)
}
}
但是我每次运行顺序都不一样
有什么想法吗?
谢谢
The issue is that inside the loop for I make http.get requests that return observables and I loose the control
每个异步调用可能需要不同的时间量,因此可能不会 return 以相同的顺序响应。
And since I need to go through and calculate the values in that order to show them in a graph, this is not worth it and I do not know how to get out of here. Any idea Please?
解决方法是:
1.Convert 请求数组到异步响应数组(可观察对象或承诺)
2.Wait 直到所有请求都得到解决并且所有响应都使用 forkJoin()
或 Promise.all()
3.Process 所有回复。
getGastadoRealizado() {
// ...
const responses = this.etiquetasEjeX.map(etiqueta => { // Converted for loop to map
return this.dataService.getGastadoRealizadoEnMesYAño(
// ...
).pipe(tap(item => {
// ...
}))
})
forkJoin(responses).subscribe(items => {
items.forEach(item => {
//...
})
})
}
更新:
对于更新后的问题,如果您return 承诺服务,那么...
getGastadoRealizado() {
// ...
const responses = this.etiquetasEjeX.map(etiqueta => { // Converted for loop to map
return this.dataService.getGastadoRealizadoEnMesYAño(
// ...
)
})
Promise.all(responses).then(items => {
items.forEach(item => {
//...
})
})
}