我有一个功能可以根据订单/请求的数据生成报告。里面的函数有一个循环来查看要产生的展示总数,然后执行一系列操作。
问题是我无法让它线性完成,即先完成一个函数,然后再前进到下一行。
主要功能是:
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(GetProtocol()) 和 if(CheckPrintEnd()) 中遇到问题,因为它首先在 GetProtocol() 完成之前执行 console.log("Order Cyclecompleted.") ,因此我不能根据需要关闭打印。
这些功能是:
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;
}
});
}
我尝试了不同的事情,比如用 Promise 来做,在 GetProtocol 和 CheckPrintEnd 中返回 true/false,异步/等待......但没有什么效果。
所以,我希望代码同步运行,先完成一个函数,然后再继续下一个,因为下一个函数需要前一个函数的值。
下面是我尝试摆脱承诺和可观察量的混合,我仅使用 rxjs 来创建一个值流,该值流向下到单个订阅,请仔细阅读所有操作员的文档以更好地理解实现,但是我添加了注释,以便您更好地理解我的实现!
request() {
const apiArray$ = of([]);
for (let index = 1; index <= this.numLabels; index++) {
this.p_orderRequest.RequestId = this.generateRandomId()
.toString()
.substring(0, 9);
// the below sequence gets executed for each element added by the for loop
const apiSequence = forkJoin([
this.porderService
.InsertRequest(this.p_orderRequest),
// subscribe cannot be used inside a function, which outputs to the if condition it will always be false, to solve this, we can use a fork join, to preevaluate the conditions simulatenously
this.porderService.GetProtocol(this.p_orderRequest.RequestId).pipe(
// great operator to transform the inner values of a stream!
map(data => {
if (data.type === 'success') {
return true;
} else {
return false;
}
})),
// subscribe cannot be used inside a function, which outputs to the if condition it will always be false, to solve this, we can use a fork join, to preevaluate the conditions simulatenously
this.porderService.CheckPrintEnd(this.p_orderRequest).pipe(
// great operator to transform the inner values of a stream!
map(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;
}
}))
]).pipe(
// great for sequential executions, first one runs, then the below code
switchMap(([data, protocolBool, checkPrintEndBool]) => {
if (data.type === 'success' || data.type === 'error') {
if (protocolBool) {
console.log('Protocol correct');
if (checkPrintEndBool) {
if (this.blnFinished) {
if (this.p_orderRequest.result == 'OK') {
return this.porderService
.SaveOrderRegisterControl(this.p_orderRequest)
.pipe(
// great for sequential executions, first one runs, then the below code
switchMap(() => {
// assuming you want this to be executed after the top one!
return this.porderService
.SaveSystemAudit(this.p_orderRequest);
})
);
}
return this.porderService
.DeleteRequest(this.p_orderRequest)
}
}
// for all the other cases, we return the default value
// no case was executed!
return of(false);
}
})
)
// adding the APIS to the for loop
apiArray$.push(apiSequence);
}
// runs this observable array in parallel, returns all the values at once!
forkJoin(apiArray$).subscribe((output: any) => {
this.numLabelsPrinted = output.length;
console.log(output);
});
}