xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

前端如何取消一个 Fetch API 请求 All In One

前端如何取消一个 Fetch API 请求 All In One

cancel http request

AbortController

signal


const controller = new AbortController();

controller;
// AbortController {signal: AbortSignal}signal: AbortSignalaborted: falseonabort: nullreason: undefined[[Prototype]]: AbortSignal[[Prototype]]: AbortController

controller.abort();
// undefined

controller;
// AbortController {signal: AbortSignal}signal: AbortSignal {aborted: true, reason: DOMException: signal is aborted without reason at <anonymous>:1:12, onabort: null} [[Prototype]]: AbortController

https://developer.mozilla.org/en-US/docs/Web/API/AbortController

demos

使用 AbortController API 实现 debounce 防抖效果 ✅

// 外部变量
let controller;
const url = "video.mp4";
// const url = "https://mdn.github.io/dom-examples/abort-api/sintel.mp4";
const downloadBtn = document.querySelector('.download');
const abortBtn = document.querySelector('.abort');
abortBtn.addEventListener('click', function() {
  if (controller) {
    controller.abort();
    console.log('Download aborted');
  }
});
downloadBtn.addEventListener('click', fetchVideo);

function fetchVideo() {
  // 外部变量赋值
  controller = new AbortController();
  const signal = controller.signal;
  fetch(url, { signal })
    .then(function(res) {
      console.log('Download complete', res.text());
    })
    .catch(function(err) {
      console.log('Download error: ' + err.message);
    });
}

image

https://mdn.github.io/dom-examples/abort-api/

demos

let controller;

function fetchVideo() {
  controller = new AbortController();
  const signal = controller.signal;
  fetch(url, { signal })
    .then(response => {
      console.log('Download complete', response);
    })
    .catch(err => {
      console.log('Download error: ' + err.message);
    });
}

(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!

abortable fetch

https://developers.google.com/web/updates/2017/09/abortable-fetch

demo

https://fetch-svg-abort.glitch.me/

blogs

https://www.carlrippon.com/cancelling-fetch-in-React-and-typescript/

https://segmentfault.com/a/1190000039841110

https://gist.github.com/carlrip/4f01187cef825f3b7d8cc953ab876b8b

// TS & React

import React from "react";

type Character = {
  name: string;
};

interface PromiseWithCancel<T> extends Promise<T> {
  cancel: () => void;
}
function getCharacter(id: number) {
  const controller = new AbortController();
  const signal = controller.signal;
  const promise = new Promise(async (resolve) => {
    try {
      const response = await fetch("https://swapi.dev/api/people/" + id, {
        method: "get",
        signal,
      });
      const data = await response.json();
      assertIsCharacter(data);
      resolve(data);
    } catch (ex: unknown) {
      if (isAbortError(ex)) {
        console.log(ex.message);
      }
    }
  });
  (promise as PromiseWithCancel<Character>).cancel = () => controller.abort();
  return promise as PromiseWithCancel<Character>;
}

function assertIsCharacter(data: any): asserts data is Character {
  if (!("name" in data)) {
    throw new Error("Not character");
  }
}

function isAbortError(error: any): error is DOMException {
  if (error && error.name === "AbortError") {
    return true;
  }
  return false;
}

export function App() {
  const [status, setStatus] = React.useState<
    "loading" | "loaded" | "cancelled"
  >("loading");
  const [data, setData] = React.useState<Character | undefined>(undefined);
  const [query, setQuery] = React.useState<
    PromiseWithCancel<Character> | undefined
  >(undefined);
  React.useEffect(() => {
    const q = getCharacter(1);
    setQuery(q);
    q.then((character) => {
      setData(character);
      setStatus("loaded");
    });
  }, []);

  if (status === "loading") {
    return (
      <div>
        <div style={{ margin: "20px 0px 5px" }}>loading ...</div>
        <button
          onClick={() => {
            query?.cancel();
            setStatus("cancelled");
          }}
        >
          Cancel
        </button>
      </div>
    );
  }
  if (status === "cancelled") {
    return <div>Cancelled</div>;
  }

  return <div>{data && <h3>{data.name}</h3>}</div>;
}

https://davidwalsh.name/cancel-fetch

https://juejin.cn/post/6844904113130438663

refs



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-03-19 23:20  xgqfrms  阅读(218)  评论(2编辑  收藏  举报