I tried to do following function with concat map. but i'm not sure what is the correct way for that.
//Req 01
await this.shippingInfoService.getShipmentInfoByCardId(this.data.CardId).then(async (shipmentData) => {
if (shipmentData != undefined) {
if (shipmentData.ShipmentId !== null && shipmentData.ShipmentId !== "") {
//If shipment is assigned
let shipmentId = shipmentData.ShipmentId;
let contract = JSON.parse(sessionStorage.getItem(SITE_DETAILS_KEY)).Contract;
let printObj = {
"ShipmentId": Number(shipmentId),
"Contract": contract
}
//Second Req
await this.orderDetailsService.printBillOfLading(printObj).then(async () => {
await this.orderDetailsService.getBillOfLeadingPdfInfo(shipmentId).then(async (response) => {
if (response.ResultKey === null || response.Id === null) {
const dialogConfig = new MatDialogConfig();
dialogConfig.data = "The information needed to generate a report isn't available.";
dialogConfig.disableClose = true;
this.dialog.open(ErrorDialogComponent, dialogConfig);
//Hide Loading indicator
this.store.dispatch(setLoadingSpinner({showLoading: false}));
} else {
// 3rd Req
let url = await this.orderDetailsService.generateBillOfLadingPdfUrl(response.ResultKey, response.Id);
await window.open(url.url, "_blank");
//Hide Loading indicator
await this.store.dispatch(setLoadingSpinner({showLoading: false}));
}
});
});
} else {
//If shipment is not assigned
//Hide Loading indicator
this.store.dispatch(setLoadingSpinner({showLoading: false}));
//Error
const dialogConfig = new MatDialogConfig();
dialogConfig.data = "Shipment needs to be connected";
dialogConfig.disableClose = true;
this.dialog.open(ErrorDialogComponent, dialogConfig);
}
}
})
- Request 02 is depend on Request 01
- Request 03 is depend on Request 02
Need to refactor above code with rxjs operators.
CodePudding user response:
This is a refactoring of your code, altering as little as possible (to a point). I don't think this is the most idiomatic way to write RxJS, but then I also wouldn't write Promises as above either.
I can't test any of this, so this is the shape of an answer, and not an answer unto itself. Maybe it'll get you started...
Best of luck:
//Req 01
from(this.shippingInfoService.getShipmentInfoByCardId(this.data.CardId)).pipe(
filter(shipmentData => shipmentData != undefined),
tap(shipmentData => {
if (shipmentData.ShipmentId !== null && shipmentData.ShipmentId !== "") {
throw "Shipment needs to be connected"
}
}),
// Second Req because shipment is assigned
concatMap(shipmentData => this.orderDetailsService.printBillOfLading({
"ShipmentId": Number(shipmentData.ShipmentId),
"Contract": JSON.parse(sessionStorage.getItem(SITE_DETAILS_KEY)).Contract
}).pipe(
map(_ => Number(shipmentData.ShipmentId))
)
),
concatMap(id => this.orderDetailsService.getBillOfLeadingPdfInfo(id)),
tap(response => {
if ( response.ResultKey === null || response.Id === null) {
throw "The information needed to generate a report isn't available."
}
}),
// 3rd Req
concatMap(response =>
this.orderDetailsService.generateBillOfLadingPdfUrl(response.ResultKey, response.Id)
),
// Catch errors thrown above
catchError(error => {
// This isn't really comprehensive error management for obvious reasons.
// I'm assuming the only errors are one of the two strings thrown above.
const dialogConfig = new MatDialogConfig();
dialogConfig.data = error;
dialogConfig.disableClose = true;
this.dialog.open(ErrorDialogComponent, dialogConfig);
// Returning empty means we don't propogate this error
return EMPTY;
}),
// Always finish by Hiding Loading indicator
finalize(() => this.store.dispatch(setLoadingSpinner({showLoading: false})))
).subscribe(
url => window.open(url.url, "_blank")
);
CodePudding user response:
- Not everything has to be an anonymous inline function, and 2) functions can return something. The general shape of the sequence looks more or less like that:
getShipmentInfo().pipe(
map(response => parseShipmentData(response)),
switchMap(printObj => forkJoin([
// Why do them in sequence? You aren't using results from `printBillOfLading` for anything
printInvoice(printObj),
getPdfInfo(printObj.ShipmentId),
]),
switchMap(([nevermind, pdfResponse]) => handlePdfResponse(pdfResponse))
)
with parseShipmentData, printInvoice, getPdfInfo and handlePdfResponse filled with the relevant pieces of logic from your original code. BTW mixing await with then and nesting async functions is unnecessary and only obfuscates your code.
