Reputation: 301
I'm desperated with this code.
getSumOfSpecificDayWeek(daysMonth: any, callback: any){
var data = [];
var that = this;
daysMonth.forEach(function(day){
that.statsService.getData(that.userid, day).subscribe(async (res: any) => {
data = JSON.parse(JSON.stringify(res));
console.log(that.data);
that.data = that.data.map( function(v, i) {
return v + data[i];
});
});
});
callback("this should be at the end");
}
Here what I'm doing is getting arrays from a server and summing it up into that.data per each component of it, this works fine but at the end I want to average the result, at this very moment I'm just calling to callback to show a message to checking whether it occurs finally, but no, "this should be at the end" is displayed before the loop starts summing.
mycallback(arg: any){
console.log(arg);
}
This is the main call to the method
this.getSumOfSpecificDayWeek(daysMonth, this.mycallback);
Upvotes: 0
Views: 1182
Reputation: 2999
A little more RxJS, but more elegant way:
getSumOfSpecificDayWeek(daysMonth: any, callback: any){
var data = [];
var that = this;
let getCalls = []; // <--- This will contain all of your observables.
daysMonth.forEach(function(day){
const observable = that.statsService.getData(that.userid, day);
getCalls.push(observable); // <--- Add the current observable to the array.
observable.subscribe(async (res: any) => {
data = JSON.parse(JSON.stringify(res));
console.log(that.data);
that.data = that.data.map( function(v, i) {
return v + data[i];
});
});
});
// And here, you can use `callback`:
Observable.forkJoin(...getCalls).subscribe(results => {
callback("this should be at the end");
});
}
Upvotes: 3
Reputation: 2487
you need to manage the observable in another way
you need to execute a array of async operations and then execute a callback function
your code should look like
getSumOfSpecificDayWeek(daysMonth: any, callback: any){
var data = [];
var that = this;
Observable.mergeArray(daysMonth.map(day=> that.statsService.getData(that.userid, day)).subscribe((arrOfResponses)=>{
// do your job with the data
callback("this should be at the end"); })
}
Upvotes: 0
Reputation: 9642
So, this kind of thing is sadly a little confusing in Javascript. What this will do is to fire off a request for everything in daysMonth
in the background, then call your callback. The async requests you fired off previously will then complete at some point.
Ultimately, what you need to do is to detect when you've done all the work, then fire off your callback. Take a look at something like this instead:
var numDone = 0;
daysMonth.forEach(function(day){
that.statsService.getData(that.userid, day).subscribe(async (res: any) => {
numDone++;
data = JSON.parse(JSON.stringify(res));
console.log(that.data);
that.data = that.data.map( function(v, i) {
return v + data[i];
});
if(numDone == daysMonth.length) {
callback("All done!")
}
});
});
Effectively, we can do some work in the getData()
callback, and if we're the last thing running, we then call the outer callback with any data we want.
Of course, this can get messy. The async
library abstracts all this quite nicely, so you might be able to use async.map
for your purposes too.
Upvotes: 0