UNPKG

2.29 kBJavaScriptView Raw
1import { defineMiddleware } from 'fatcher';
2
3const roadMap = {};
4function 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
68function isAbortError(error) {
69 return error instanceof DOMException && error.name === "AbortError";
70}
71
72export { aborter, isAbortError };