[英]RxJs: multiple requests followed by one request via concatMap not working
我做了一个 api 调用,它返回一个数组。 我需要遍历这个数组并为每个项目执行一个新请求。 以下代码工作正常:
return this.expeditionService.getTranssmartBookingXml(request).pipe(
concatMap((response) => {
return from(response.barcodes).pipe(
concatMap((barcode) => {
return this.expeditionService.saveTranssmartBarcode({
...saveBarcodeRequest,
barcode: barcode,
});
})
);
})
);
但是,当所有项目都完成后,我想提出另一个请求。 只有一个。
但是当我使用以下代码时,当 from 数组中的第一项完成时,该过程停止。
return this.expeditionService.getTranssmartBookingXml(request).pipe(
concatMap((response) => {
return from(response.barcodes).pipe(
concatMap((barcode) => {
return this.expeditionService.saveTranssmartBarcode({
...saveBarcodeRequest,
barcode: barcode,
});
}),
concatMap(() => {
const transsmartSaveShipmentRequest: TranssmartSaveShipmentRequest =
{
reference: this.shipmentReferenceResult!.reference,
price: this.transsmartDoBookingResponse!.price,
trackingUrl: this.transsmartDoBookingResponse!.trackingUrl,
};
return this.expeditionService.saveTranssmartShipment(
transsmartSaveShipmentRequest
);
})
);
})
我也有一些稍微修改过的代码,但随后对数组中的每个项目执行了最终请求,它只需要执行一次。
有人知道如何解决这个问题吗? 提前致谢!!
from
function 将高阶运算符(如concatMap
)连接到 stream 将为源数组的每个元素触发它。 您需要使用类似last
的操作符将 stream 限制为 stream 特定点的最后一个元素。
虽然它不会对内部或外部last
的管道产生影响,但我更喜欢将它管道到外部 observable,因为它看起来更优雅。
return this.expeditionService.getTranssmartBookingXml(request).pipe(
concatMap((response) => {
return from(response.barcodes).pipe(
concatMap((barcode) => {
return this.expeditionService.saveTranssmartBarcode({
...saveBarcodeRequest,
barcode: barcode,
});
})
)
}),
last(),
concatMap(() => {
const transsmartSaveShipmentRequest: TranssmartSaveShipmentRequest = {
reference: this.shipmentReferenceResult!.reference,
price: this.transsmartDoBookingResponse!.price,
trackingUrl: this.transsmartDoBookingResponse!.trackingUrl,
};
return this.expeditionService.saveTranssmartShipment(
transsmartSaveShipmentRequest
);
})
);
您可以使用toArray将一堆单独的发射组合成一个数组,或者您可以使用concat只处理两个可观察的序列,因为您似乎真的不想要保存条形码的结果。
我更喜欢第二种,但两者都希望你想要并且看起来比你拥有的更干净。
ToArray 方法
return this.expeditionService.getTranssmartBookingXml(request).pipe(
concatMap(res => from(res.barcodes)),
concatMap(barcode => this.expeditionService.saveTranssmartBarcode({
...saveBarcodeRequest,
barcode: barcode,
})),
toArray(),
concatMap(() => /* save TrannsmartShipmentRequest... */)
);
连接方法
// you don't have to create variables as you can place the streams directly in concat.
const saveBarCodes$ = this.expeditionService.getTranssmartBookingXml(request).pipe(
concatMap(res => from(res.barcodes)),
concatMap(barcode => this.expeditionService.saveTranssmartBarcode({
...saveBarcodeRequest,
barcode: barcode,
}))
);
// no point in this being inside an operator.
const saveShipmentRequest: TranssmartSaveShipmentRequest = {
reference: this.shipmentReferenceResult!.reference,
price: this.transsmartDoBookingResponse!.price,
trackingUrl: this.transsmartDoBookingResponse!.trackingUrl
};
const saveShipment$ = this.expeditionService.saveTranssmartShipment(saveShipmentRequest);
return concat(saveBarCodes$, saveShipment$);
如果将toArray添加到saveBarCode$的末尾可能会很有用,因为这会导致返回结果是条形码保存结果数组和保存货件的结果的元组。
这是我基于 Michael D 的回答的最终解决方案。 最终的 concatMap 应该导致在 printViaIpAddress 方法中的每个项目的 subscribe 方法中点击成功方法。 这完美地工作。
Daniel 的回答最终导致每个连接的 observable(我认为)都达到了成功方法,这并不是我在这种情况下想要的。
return this.expeditionService.getTranssmartBookingXml(request).pipe(
concatMap((response) => {
saveShipmentRequest.price = response.price;
saveShipmentRequest.trackingUrl = response.trackingUrl;
return from(response.barcodes).pipe(
concatMap((barcode) => {
return this.expeditionService.saveTranssmartBarcode({
...saveBarcodeRequest,
barcode: barcode,
});
})
);
}),
last(),
concatMap(() => {
return this.expeditionService.saveTranssmartShipment(
saveShipmentRequest
);
}),
concatMap(() => {
return this.expeditionService.getTranssmartLabels(
transsmartBonnenXmlRequest
);
}),
concatMap((response) => {
return from(response.values).pipe(
concatMap((label) => {
return this.expeditionService.printViaIpAddress({
...printTranssmartRequest,
label,
});
})
);
})
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.