Angular RXJS 顺序多重 post 请求
Angular RXJS Sequential multiple post request
我尝试使用 concat 映射执行以下功能。但我不确定正确的方法是什么。
//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);
}
}
})
- 请求 02 依赖于请求 01
- 请求 03 依赖于请求 02
需要用 rxjs 运算符重构上面的代码。
这是对您的代码的重构,尽可能少地更改(在一定程度上)。我不认为这是编写 RxJS 最惯用的方式,但我也不会像上面那样编写 Promises。
我无法测试任何这些,所以这是答案的 形状 ,而不是答案本身。也许它会让你开始...
祝你好运:
//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")
);
- 并非所有内容都必须是匿名内联函数,并且 2) 函数可以 return 某些东西。序列的一般形状看起来或多或少是这样的:
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))
)
parseShipmentData
、printInvoice
、getPdfInfo
和 handlePdfResponse
填充了原始代码中的相关逻辑片段。顺便说一句,将 await
与 then
混合并嵌套 async
函数是不必要的,只会混淆您的代码。
我尝试使用 concat 映射执行以下功能。但我不确定正确的方法是什么。
//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);
}
}
})
- 请求 02 依赖于请求 01
- 请求 03 依赖于请求 02
需要用 rxjs 运算符重构上面的代码。
这是对您的代码的重构,尽可能少地更改(在一定程度上)。我不认为这是编写 RxJS 最惯用的方式,但我也不会像上面那样编写 Promises。
我无法测试任何这些,所以这是答案的 形状 ,而不是答案本身。也许它会让你开始...
祝你好运:
//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")
);
- 并非所有内容都必须是匿名内联函数,并且 2) 函数可以 return 某些东西。序列的一般形状看起来或多或少是这样的:
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))
)
parseShipmentData
、printInvoice
、getPdfInfo
和 handlePdfResponse
填充了原始代码中的相关逻辑片段。顺便说一句,将 await
与 then
混合并嵌套 async
函数是不必要的,只会混淆您的代码。