I'm trying to automatize a process of updating some data in the backend of my program. I'm using my Angular frontend, where I created a function only the master user can access and that should make him login in every administration (tenant), where it will download some objects with some wrong data inside, ask from a google service the right data and update the data in the backend, and do all this operations for each tenant.
I thougt of writing each of this operations as an observable and using concat to do everything in order, but before even finishing getting the right data, which I do inside a tap, it alredy tries to login in the next tenant, so when it actually has the right data he wont be able to upload them to the backend since it will refuse them as from the wrong tenant.
I think this problem is caused by the long operations needed in the tap (and there are some stuff I'll need to do that will require even more time),.
This is my code snippet (without unrelated stuff):
const obsList = [] as Observable<any>[];
this.assignedTenants.forEach(tenant => {
const obsList2 = [] as Observable<any>[];
obsList.push(this.authenticationService.login(new Credentials(usr, psw), tenant.id));
obsList.push(this.structureService.getStructuresWithWrongAltitude()
.pipe(tap(structuresReceived => {
obsList2 = [] as Observable<any>[];
if (structuresReceived != null && structuresReceived.length > 0) {
structuresReceived.forEach(s => {
this.getElevation(new google.maps.LatLng(s.centro.coordinates[0], s.centro.coordinates[1]))
.then(a => {
s.centroAltitudine = a;
this.obsList2.push(this.structureService.putStructure(s));
})
.catch();
});
}
})));
obsList.push(forkJoin(obsList2)
.pipe(tap(() => this.storageService.logout())));
});
concat(...obsList).subscribe();
As you can see the this code should create and execute 3 observables for each tenant, the first one used to login, the second one to get the wrong data, get the right data and prepare for the third, which will update the data. As I said, usually when entering the tap from the second observable, the getStructuresWithWrongAltitude one, I can alredy see by using logs that it tries to login to other tenants.
My theory is that as soon as it gets the wrong data it tries to execute the third observable, which is still void, and go to the next tenant, but I dont know how to fix this.
I would need a way for the second observable to not emit until the tap is completed, or another way to prevent the concat to go on before other operations have finished
Thank you for your help
EDIT:
I was able to fix this by making the getElevation (which returns a promise) to an observable list, which would in turn create a new observable list to save the data.
As I said before I need to do something very similar, with the difference that this time the tap will actually have to do a lot of calculations that will take a long time, so I wont be able to use the same fix, as such my question remains: can I make the concat wait until the tap is finished?
EDIT 2 for clarification
As I said in my last edit, that specific example got solved by converting the stuff inside the tap into other observables, but I have almost the same problem with another function
this function needs to find files inside a folder, before uploading them
const folderInput = this.folderInput.nativeElement;
folderInput.onchange = () => {
this.filesUploaded = folderInput.files;
const obsList = [] as any[];
this.assignedTenants.forEach(tenant => {
const obsList2 = [] as Observable<any>[];
obsList.push(this.authenticationService.login(new Credentials(usr, psw), tenant.id));
obsList.push(this.fileService.getAll()
.pipe(
tap(filesReceived => {
if (filesReceived != null && filesReceived.length > 0) {
console.log('upload picture: received list of files to update');
let i = filesReceived?.length;
filesReceived?.forEach(f => {
const pathReceived = (f.originalFilename as string).substr(1).split('\\');
let found = false;
let index = -1;
// searching the file in the folder
//...
if (found) {
console.log('found a file');
const selectedFile = this.filesUploaded[index];
const formData = new FormData();
formData.append('file', selectedFile, selectedFile.name);
obsList2.push(this.fileService.updateFile(formData, f.id));
}
i--;
});
console.log('upload picture: updated obsList2');
obsList.push(forkJoin(obsList2).subscribe(() => {
console.log('upload picture: uploaded pictures');
this.storageService.logout();
}));
}
}))
);
});
this.loadingIndicatorService.loading$.next(true);
let counter = obsList.length;
concat(...obsList).subscribe(() => {
counter--;
console.log('upload pictures: remaining phases: ' + counter);
if (counter <= 0) {
this.loadingIndicatorService.loading$.next(false);
}
});
};
folderInput.click();