I have a function which generates reports from the data of an order/request. The function inside has a loop to see the total number of impressions to make and then a series of actions to do.
The problem is that I can’t get it to be done linearly, that is, first finish a function before advancing to the next line.
The main function is:
async request(){
for (let index = 1; index <= this.numLabels; index++) {
let time: number = 0;
this.p_orderRequest.RequestId=this.generateRandomId().toString().substring(0,9);
this.porderService.InsertRequest(this.p_orderRequest).subscribe(async data => {
//Start interval with promise to ensure not continue in loop for??
const responseRequest = await new Promise<void>((resolve, reject)=>{
this.timerCheck = setInterval(() => {
time = time +this.INTERVAL_DURATION_MS;
if(data.type === 'success' || data.type ==='error'){
if(this.GetProtocol()){
console.log("Protocol correct")
if(this.CheckPrintEnd()){
if(this.blnFinished){
if(this.p_orderRequest.result=="OK"){
this.porderService.SaveOrderRegisterControl(this.p_orderRequest).subscribe();
this.porderService.SaveSystemAudit(this.p_orderRequest).subscribe();
}
this.porderService.DeleteRequest(this.p_orderRequest).subscribe();
}
}
}
time = 0;
console.log("Cycle cycle completed.")
clearInterval(this.timerCheck)
resolve();
}else if(time>this.DEFAULT_TIME_OUT){
this.p_orderRequest.result="NG:TIMEOUT=" + time
this.UpdateRequest(this.p_orderRequest, "TIME_OUT");
clearInterval(this.timerCheck);
resolve();
}else{
console.log("Waiting for the server...")
}
},1000);
})
this.numLabelsPrinted++
});
}
}
If I get a response from the server, I start a series of functions until the cycle ends and the interval closes so I can move on to the next print if there is one. If I do not get a response within the established time, I have a timeout configured, although it is not this part that is failing me.
Mostly, I have the problem in if(GetProtocol()) and if(CheckPrintEnd()) since it is first doing the console.log("Order cycle completed.") before GetProtocol() finishes, and therefore I can’t close the print as I need.
Those functions are these:
GetProtocol(): any{
this.porderService.GetProtocol(this.p_orderRequest.RequestId).subscribe(data => {
if (data.type === 'success') {
return true;
} else {
return false;
}
});
}
CheckPrintEnd():any{
this.porderService.CheckPrintEnd(this.p_orderRequest).subscribe( data => {
if (data.type === 'success') {
this.p_clsRequest = JSON.parse(data.data.toString()) as POrderRequest;
this.blnFinished = !!(this.p_orderRequest.porderValue);
return true;
} else {
return false;
}
});
}
I tried different things like do it with promises, return true/false in GetProtocol and CheckPrintEnd, Async/await…but nothing works good.
So, I want the code to run synchronously, first finishing one function before continuing to the next because the next one needs the values โโof the previous one.
2
Answers
Below is my atempty to get rid of the mixing of promises and observables, I have used only rxjs to create a stream of values, that flow down to a single subscribe, do go through the docs for all the operators to better understand the implementation, but I have added comments, for you to better understand my implementation!
If you are familiar with rxjs you could forkJoin or zip all the request together to one stream (Observable) and subscribe to it in one place.
I’ve put together a quick example how I would solve this. The conditions or variables are just trying to replicate your code. Hope this gives you some inspiration to you.