I am trying to send httpclient in my Observable
function, it will run without the HttpClient Complete.
Here is a demo code which is used to reproduce
test() {
this.test2()
.pipe(
mergeMap((result) => {
console.log(result[0]);
return of([]);
})
)
.subscribe();
}
test1(): Observable<any> {
return of(this.getStudents());
}
test2(): Observable<any> {
return this.test1().pipe(
mergeMap((result) => {
if (result) {
result.map((rr) => {
if (rr.age == 1) {
this.client
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.subscribe((res) => {
console.log(res);
rr.age = rr.age * 10000;
});
} else {
rr.age = rr.age * 10;
}
return rr;
});
}
return of(result);
})
);
}
getStudents(): Student[] {
return [{ age: 1 }, { age: 2 }, { age: 3 }];
}
This is Student
export class Student {
age: number;
}
For expected result, the console.log(res);
should return before console.log(result[0]);
.
I have tried many ways like .toPromise
, and async await
, but fail to make it work.
You could fork a test version below:
https://stackblitz.com/edit/save-file-to-drive-7dawzd?file=src/app/app.component.ts
Based on your expected result, you need the api call to finish first before printing the Student[0].
The issues on your code:
console.log(result[0])
prints first before console.log(res);
because the api call isn't done yet.I used a couple of RXJS operators to get what you want.
mergeMap
to flatten the inner observableof
to convert the student array into an observablemap
to transform the current array into a a new array with their corresponding new ageforkJoin
- we wrapped multiple requests into one observable and will only return when a response has been received for all requests.This is certainly only one way to do it and there might be other better ways.
test() {
this.test2()
.pipe(
mergeMap((result) => {
console.log(result);
if (result && result.length > 0) {
console.log(result[0]);
}
return of([]);
})
)
.subscribe();
}
test1(): Observable < Student[] > {
// return of(null);
return of(this.getStudents());
}
test2(): Observable < Student[] > {
return this.test1().pipe(
mergeMap((result) => {
if (!result) {
return of(result);
}
return forkJoin(
result.map((rr) =>
rr.age === 1 ?
this.client
.get('https://api.coindesk.com/v1/bpi/currentprice.json')
.pipe(
map((res) => {
console.log(res);
return (rr.age = rr.age * 10000);
})
) :
of ((rr.age = rr.age * 10))
)
).pipe(
map((paths) => {
return result.map((e, index) => ({
age: paths[index],
}));
})
);
})
);
}
getStudents(): Student[] {
return [{
age: 1
}, {
age: 2
}, {
age: 3
}];
}
I modified the stackblitz you created to mock the solution.