中止先前的请求后无法发出新的提取请求

时间:2020-08-14 12:42:34

标签: javascript xmlhttprequest fetch

我需要更改一个参数,该参数定义应从请求中获取哪些数据,此应用程序还需要在每个固定的时间间隔内刷新。如果用户在上一个刷新请求的中间更改了感兴趣的参数,则事情开始变得奇怪,并且发生了一些意外行为。

所以我的方法是在启动新请求之前中止所有先前的请求,但是在使用await controller.abort()之后,似乎从未触发下一个请求,我是否需要清除信号或类似的东西?

const controller = new AbortController();
const async fetchData = (url, body = null) => {
  let data;
  const signal = controller.signal;
  const headers = { ... };
  response = await fetch(url, body ? {
    method: "POST",
    body: JSON.stringify(body),
    signal,
    headers
  } : { headers, signal });;
  data = await response.json()
  return data
}

const firstData = await fetchData(url1, body1);
await controller.abort();
const secondData= await fetchData(url2, body2);

发生的情况是secondData始终是undefined,实际上第二个请求从未发生(查看网络流量)。如果我停止了源代码并尝试在await fetchData(url2)执行之后运行.abort(),则会提示错误信息,提示Uncaught SyntaxError: await is only valid in async function,或者如果我尝试在没有await的情况下运行它,则会返回未完成的承诺,但在流量标签中看不到实际的请求。


已解决

应用在我在函数上创建的包装器的ansewr上建议的内容,以便每次都调用新的控制器。

let controller = null;
let fetchData = null;
const initializeFetchData = () => {
  const controller = new AbortController();
  const async fetchData = (url, body = null) => {
    let data;
    const signal = controller.signal;
    const headers = { ... };
    response = await fetch(url, body ? {
      method: "POST",
      body: JSON.stringify(body),
      signal,
      headers
    } : { headers, signal });;
    data = await response.json()
    return data
  }
}

initializeFetchData();
const firstData = await fetchData(url1, body1);
controller.abort();
initializeFetchData();
const secondData= await fetchData(url2, body2);

1 个答案:

答案 0 :(得分:1)

您正在为两个不同的请求使用相同的AbortController。在.abort()上调用AbortController之后,您已经更新了AbortSignal的状态,然后使第二个请求无效。

如果您想要这种行为,则应为每个请求使用单独的AbortController。当然,如果您希望能够一次放弃所有AbortController,则完全可以接受将fetch重用于多个.abort()

其他几点...

  • void是一种同步方法,它返回await,因此在调用.abort()时不需要fetch前缀。
  • 在您的代码示例中,第一个请求将永远不会因为您正在等待而被中止。.abort()请求将在调用<ListView [items]="items"> <ng-template let-item="item"> <GridLayout class="list-view" rows="auto, *"> <StackLayout row="0" class="list-view__content" (tap)="toggleAccordion(item)"> <GridLayout columns="*, auto"> <FlexboxLayout col="0" alignItems="center"> <Label class="list-view__content__headline" [class.has-selected]="item.count > 0" textWrap="true" [text]="item.title"></Label> <Label class="list-view__content__count" textWrap="true" *ngIf="item.count > 0" [text]="item.count"></Label> </FlexboxLayout> <StackLayout col="1"> <Image *ngIf="item.opened" src="font://&#xf077;" class="fas" width="15"></Image> <Image *ngIf="!item.opened" src="font://&#xf078;" class="fas" width="15"></Image> </StackLayout> </GridLayout> </StackLayout> <StackLayout row="1" *ngIf="item.values && item.values.length > 0 && item.opened"> <ns-multi-select-search [data]="item (selectionChange)="onSelectionChange($event)"></ns-multi-select-search> </StackLayout> </GridLayout> </ng-template> </ListView> 之前完成。