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.