处理异步动作的取消取决于我们正在执行异步动作的类型和方式。
我假设异步操作的类型是HTTP请求。因此,我们有几种选择方式来执行实际的HTTP请求:
- 使用Angular本身的 HttpClient (最常见的情况和最佳实践!)
- 使用 Axios (Afaik是Fetch API的包装器)
- 使用浏览器本身提供的 Fetch API
HttpClient
当使用Angular本身的HttpClient
服务时,建议与RxJs
结合使用。因此,在您的情况下,我将切换回上面所述的Observable解决方案。为什么?:
- HttpClient本身使用
RxJs
并返回Observables作为默认值
-
RxJs
与HttpClient
的组合使使用其 switchMap 运算符 轻松取消正在进行的请求
- 请注意, switchMap 本身不会取消HTTP请求或保留其逻辑。它仅在订阅内部流时调用unsubscribe。请求取消逻辑由 HttpClient 的实现(或多或少)提供,该实现在取消订阅回调中返回取消逻辑。
- 不幸的是,编写正确的
RxJs
代码并避免多个订阅或嵌套订阅并不容易。在您的情况下,我将尝试创建(假设)点击事件流并使用:
- switchMap来展平流(与
flatMap
相比)并取消订阅现有内部流,以防发生新的点击事件
发生。
- concatMap等到
inventoriesRequest
流完成之前,再制作populateInventoriesRequest
。
this.populateInventoryClicks$
.pipe(
switchMap(() => this.inventoryService.inventoriesRequest()),concatMap(inventories => this.inventoryService.populateInventoriesRequest(inventories)),)
.subscribe(response => {
console.log(response);
});
请查看 Stackblitz 示例。在开发控制台的“网络”标签中限制您的速度。
然后,在网络标签中,我们应该看到,在多次单击按钮时,只有最后一个请求已完成,而所有请求都被取消了。
Axios
使用Axios客户端时,我们可以使用它为我们提供的cancel
方法。如果您对他们的方法感兴趣,请看看他们的documentation。
请注意,当我们使用Axios时,来自Angular的 HttpInterceptors 不会对这些请求运行。这是为什么我不知道没有人将它与Angular结合使用的最明显原因。
获取API
Fetch API还为我们提供了中止使用fetch
进行的请求的可能性。出于与我不推荐Axios方法相同的原因,我不能推荐这种方法。但是如果您有兴趣,可以选择look。
,
您可以尝试在getCustomerInventories函数内部添加各种回调,以在希望取消承诺时解析或拒绝该承诺。
例如,如果您希望它停止并根据时间发送新消息,则可以添加
setTimeout(resolve,ms);
对此。
您可以使用Promise.race()来检索原始的等待时间或超时时间。像这样:
//keepGoing and checkGoingFunction could be whatever you need them to be but something that returns a promise that will resolve or reject when you want to "cancel" the await
var keepGoing = true;
var checkGoingFunction = function(){
return new Promise((resolve,reject) => {
while(keepGoing){
//just filling time and keeping a loop,maybe not efficient but working
}
//after it exits (when you change keepGoing to false)
resolve("timedOut");
});
}
function async populateInventories(custID){
//a promise returned by your method
var custInvPromise = this.inventoryService.getCustomerInventories(custID)
var timeoutPromise = checkGoingFunction(); //promise from timeout function
var bigPromise = Promise.race(custInvPromise,timeoutPromise);
//maybe add setTimeout(function(){keepGoing = false},5000); if you wanted to timeout after 5 seconds
var result = await bigPromise;
if(result == "timedOut"){
//resend await or whatever you need to do
} else {
this.inventories = result;
//do some stuff with Inventories
}
}
本文链接:https://www.f2er.com/2817139.html