取消异步/等待

我有如下功能

scanf

我的问题是我需要取消“正在进行的等待”请求,并像使用“订阅”一样发送“新鲜等待”请求。

以前,我的功能如下所示,其中我可以取消先前的订阅:

scanf("%f %f",&p[i][j],&p[i][j++]);

使用async / await,我可以按顺序处理任何操作,这确实很棒,并且代码可读性强,我无法使用订阅来实现,但是async / await却有其自身的缺点。

我可以一次停止多次呼叫以 populateInventories 来避免我的问题,但是我正在寻找是否可以解决我的问题的更多方法。

PS:我读到在订阅呼叫中呼叫另一个订阅或嵌套订阅不是一个好习惯。

xinyu151100 回答:取消异步/等待

处理异步动作的取消取决于我们正在执行异步动作的类型方式

我假设异步操作的类型是HTTP请求。因此,我们有几种选择方式来执行实际的HTTP请求:

  1. 使用Angular本身的 HttpClient 最常见的情况和最佳实践!
  2. 使用 Axios (Afaik是Fetch API的包装器)
  3. 使用浏览器本身提供的 Fetch API

HttpClient

当使用Angular本身的HttpClient服务时,建议与RxJs结合使用。因此,在您的情况下,我将切换回上面所述的Observable解决方案。为什么?:

  • HttpClient本身使用RxJs并返回Observables作为默认值
  • RxJsHttpClient的组合使使用其 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 示例。在开发控制台的“网络”标签中限制您的速度。 然后,在网络标签中,我们应该看到,在多次单击按钮时,只有最后一个请求已完成,而所有请求都被取消了。 enter image description here


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

大家都在问