1 | import { defineMiddleware } from 'fatcher';
|
2 |
|
3 | const roadMap = {};
|
4 | function aborter(options = {}) {
|
5 | const { timeout = 0, onAbort = null, concurrency, groupBy } = options;
|
6 | let _timeout = timeout;
|
7 | if (isNaN(_timeout) || ~~_timeout < 0) {
|
8 | console.warn("[fatcher-middleware-aborter] Timeout is not a valid number.");
|
9 | _timeout = 0;
|
10 | }
|
11 | const baseAborter = defineMiddleware(async (context, next) => {
|
12 | const abortController = new AbortController();
|
13 | if (onAbort) {
|
14 | abortController.signal.addEventListener("abort", () => onAbort());
|
15 | }
|
16 | return next({
|
17 | signal: abortController.signal,
|
18 | abort: abortController.abort.bind(abortController)
|
19 | });
|
20 | }, "fatcher-middleware-aborter");
|
21 | const timeoutAborter = defineMiddleware(async (context, next) => {
|
22 | const { signal, abort } = context;
|
23 | let timer = setTimeout(abort, _timeout);
|
24 | const release = () => {
|
25 | if (timer) {
|
26 | clearTimeout(timer);
|
27 | }
|
28 | timer = null;
|
29 | };
|
30 | signal.addEventListener("abort", release);
|
31 | const result = await next();
|
32 | release();
|
33 | return result;
|
34 | }, "fatcher-middleware-timeout-aborter");
|
35 | const concurrencyAborter = defineMiddleware(async (context, next) => {
|
36 | const { signal, abort } = context;
|
37 | const group = groupBy ? groupBy(context) : `${context.url}_${context.method}_${new URLSearchParams(context.params)}`;
|
38 | if (roadMap[group] && roadMap[group].length) {
|
39 | roadMap[group].forEach((item) => item.abort());
|
40 | }
|
41 | if (!roadMap[group]) {
|
42 | roadMap[group] = [];
|
43 | }
|
44 | roadMap[group].push({ abort, signal });
|
45 | const release = () => {
|
46 | roadMap[group] = roadMap[group].filter((item) => {
|
47 | return item.signal !== signal;
|
48 | });
|
49 | if (!roadMap[group].length) {
|
50 | delete roadMap[group];
|
51 | }
|
52 | };
|
53 | signal.addEventListener("abort", release);
|
54 | const result = await next();
|
55 | release();
|
56 | return result;
|
57 | }, "fatcher-middleware-concurrency-aborter");
|
58 | const middlewares = [baseAborter];
|
59 | if (_timeout) {
|
60 | middlewares.push(timeoutAborter);
|
61 | }
|
62 | if (concurrency) {
|
63 | middlewares.push(concurrencyAborter);
|
64 | }
|
65 | return middlewares;
|
66 | }
|
67 |
|
68 | function isAbortError(error) {
|
69 | return error instanceof DOMException && error.name === "AbortError";
|
70 | }
|
71 |
|
72 | export { aborter, isAbortError };
|