refactor: removed "abstract" buildInterceptor function

This commit is contained in:
arthurfiorette 2022-01-08 12:56:55 -03:00
parent d30b862605
commit f30e2622dd
No known key found for this signature in database
GPG Key ID: 9D190CD53C53C555
4 changed files with 211 additions and 233 deletions

View File

@ -1,35 +1,10 @@
import type { import type { CacheAxiosResponse, CacheRequestConfig } from '../cache/axios';
AxiosCacheInstance,
CacheAxiosResponse,
CacheRequestConfig
} from '../cache/axios';
export interface AxiosInterceptor<T> { export interface AxiosInterceptor<T> {
onFulfilled?(value: T): T | Promise<T>; onFulfilled?(value: T): T | Promise<T>;
onRejected?(error: any): any; onRejected?(error: any): any;
apply: (axios: AxiosCacheInstance) => void; apply: () => void;
} }
export type RequestInterceptor = AxiosInterceptor<CacheRequestConfig<unknown, unknown>>; export type RequestInterceptor = AxiosInterceptor<CacheRequestConfig<unknown, unknown>>;
export type ResponseInterceptor = AxiosInterceptor<CacheAxiosResponse<unknown, unknown>>; export type ResponseInterceptor = AxiosInterceptor<CacheAxiosResponse<unknown, unknown>>;
export function buildInterceptor(
type: 'request',
interceptor: Omit<RequestInterceptor, 'apply'>
): RequestInterceptor;
export function buildInterceptor(
type: 'response',
interceptor: Omit<ResponseInterceptor, 'apply'>
): ResponseInterceptor;
export function buildInterceptor(
type: 'request' | 'response',
{ onFulfilled, onRejected }: Omit<AxiosInterceptor<unknown>, 'apply'>
): AxiosInterceptor<unknown> {
return {
onFulfilled,
onRejected,
apply: (axios) => axios.interceptors[type].use(onFulfilled, onRejected)
};
}

View File

@ -1,11 +1,11 @@
import { deferred } from 'fast-defer'; import { deferred } from 'fast-defer';
import { buildInterceptor } from '..';
import type { AxiosCacheInstance, CacheAxiosResponse } from '../cache/axios'; import type { AxiosCacheInstance, CacheAxiosResponse } from '../cache/axios';
import type { import type {
CachedResponse, CachedResponse,
CachedStorageValue, CachedStorageValue,
LoadingStorageValue LoadingStorageValue
} from '../storage/types'; } from '../storage/types';
import type { RequestInterceptor } from './build';
import { import {
ConfigWithCache, ConfigWithCache,
createValidateStatus, createValidateStatus,
@ -14,8 +14,7 @@ import {
} from './util'; } from './util';
export function defaultRequestInterceptor(axios: AxiosCacheInstance) { export function defaultRequestInterceptor(axios: AxiosCacheInstance) {
return buildInterceptor('request', { const onFulfilled: RequestInterceptor['onFulfilled'] = async (config) => {
onFulfilled: async (config) => {
if (config.cache === false) { if (config.cache === false) {
return config; return config;
} }
@ -35,9 +34,9 @@ export function defaultRequestInterceptor(axios: AxiosCacheInstance) {
// Not cached, continue the request, and mark it as fetching // Not cached, continue the request, and mark it as fetching
emptyOrStale: if (cache.state == 'empty' || cache.state === 'stale') { emptyOrStale: if (cache.state == 'empty' || cache.state === 'stale') {
/** /**
* This checks for simultaneous access to a new key. The js event loop jumps on * This checks for simultaneous access to a new key. The js event loop jumps on the
* the first await statement, so the second (asynchronous call) request may have * first await statement, so the second (asynchronous call) request may have already
* already started executing. * started executing.
*/ */
if (axios.waiting[key]) { if (axios.waiting[key]) {
cache = (await axios.storage.get(key)) as cache = (await axios.storage.get(key)) as
@ -50,8 +49,8 @@ export function defaultRequestInterceptor(axios: AxiosCacheInstance) {
axios.waiting[key] = deferred(); axios.waiting[key] = deferred();
/** /**
* Add a default reject handler to catch when the request is aborted without * Add a default reject handler to catch when the request is aborted without others
* others waiting for it. * waiting for it.
*/ */
axios.waiting[key]?.catch(() => undefined); axios.waiting[key]?.catch(() => undefined);
@ -107,6 +106,10 @@ export function defaultRequestInterceptor(axios: AxiosCacheInstance) {
}); });
return config; return config;
} };
});
return {
onFulfilled,
apply: () => axios.interceptors.request.use(onFulfilled)
};
} }

View File

@ -1,15 +1,32 @@
import { buildInterceptor } from '..';
import type { AxiosCacheInstance } from '../cache/axios'; import type { AxiosCacheInstance } from '../cache/axios';
import type { CacheProperties } from '../cache/cache'; import type { CacheProperties } from '../cache/cache';
import type { CachedStorageValue } from '../storage/types'; import type { CachedStorageValue } from '../storage/types';
import { shouldCacheResponse } from '../util/cache-predicate'; import { shouldCacheResponse } from '../util/cache-predicate';
import { Header } from '../util/headers'; import { Header } from '../util/headers';
import { updateCache } from '../util/update-cache'; import { updateCache } from '../util/update-cache';
import { rejectResponse, setupCacheData } from './util'; import type { ResponseInterceptor } from './build';
import { setupCacheData } from './util';
export function defaultResponseInterceptor(axios: AxiosCacheInstance) { export function defaultResponseInterceptor(
return buildInterceptor('response', { axios: AxiosCacheInstance
onFulfilled: async (response) => { ): ResponseInterceptor {
/**
* Rejects cache for an response response.
*
* Also update the waiting list for this key by rejecting it.
*/
const rejectResponse = async (
{ storage, waiting }: AxiosCacheInstance,
responseId: string
) => {
// Update the cache to empty to prevent infinite loading state
await storage.remove(responseId);
// Reject the deferred if present
waiting[responseId]?.reject(null);
delete waiting[responseId];
};
const onFulfilled: ResponseInterceptor['onFulfilled'] = async (response) => {
response.id ??= axios.generateKey(response.config); response.id ??= axios.generateKey(response.config);
response.cached ??= false; response.cached ??= false;
@ -106,6 +123,10 @@ export function defaultResponseInterceptor(axios: AxiosCacheInstance) {
// Return the response with cached as false, because it was not cached at all // Return the response with cached as false, because it was not cached at all
return response; return response;
} };
});
return {
onFulfilled,
apply: () => axios.interceptors.response.use(onFulfilled)
};
} }

View File

@ -1,9 +1,5 @@
import type { Method } from 'axios'; import type { Method } from 'axios';
import type { import type { CacheAxiosResponse, CacheRequestConfig } from '../cache/axios';
AxiosCacheInstance,
CacheAxiosResponse,
CacheRequestConfig
} from '../cache/axios';
import type { CacheProperties } from '../cache/cache'; import type { CacheProperties } from '../cache/cache';
import type { CachedResponse, StaleStorageValue } from '../storage/types'; import type { CachedResponse, StaleStorageValue } from '../storage/types';
import { Header } from '../util/headers'; import { Header } from '../util/headers';
@ -21,11 +17,10 @@ export function createValidateStatus(
} }
/** Checks if the given method is in the methods array */ /** Checks if the given method is in the methods array */
export function isMethodIn(requestMethod?: Method, methodList?: Method[]): boolean { export function isMethodIn(
if (!requestMethod || !methodList) { requestMethod: Method = 'get',
return false; methodList: Method[] = []
} ): boolean {
requestMethod = requestMethod.toLowerCase() as Lowercase<Method>; requestMethod = requestMethod.toLowerCase() as Lowercase<Method>;
for (const method of methodList) { for (const method of methodList) {
@ -99,19 +94,3 @@ export function setupCacheData<R, D>(
headers: response.headers headers: response.headers
}; };
} }
/**
* Rejects cache for an response response.
*
* Also update the waiting list for this key by rejecting it.
*/
export async function rejectResponse(
{ storage, waiting }: AxiosCacheInstance,
responseId: string
) {
// Update the cache to empty to prevent infinite loading state
await storage.remove(responseId);
// Reject the deferred if present
waiting[responseId]?.reject(null);
delete waiting[responseId];
}