Last active
October 9, 2024 16:50
-
-
Save maxgaurav/48e1f309fd2afb2ab55c558c3e63d1dc to your computer and use it in GitHub Desktop.
A Interceptor system for raw ajax on rxjs to get same functionality as in angular http client interceptor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ajax, AjaxConfig, AjaxResponse } from 'rxjs/ajax'; | |
import { from, Observable, of, OperatorFunction, switchMap } from 'rxjs'; | |
export type BeforeInterceptors = (config: AjaxConfig) => Promise<AjaxConfig> | AjaxConfig | Observable<AjaxConfig>; | |
export type AfterInterceptors<T extends any = any> = (response: AjaxResponse<T>) => Observable<AjaxResponse<T>> | AjaxResponse<T> | Promise<AjaxResponse<T>>; | |
const BEFORE_INTERCEPTORS: BeforeInterceptors[] = []; | |
const AFTER_INTERCEPTORS: AfterInterceptors[] = []; | |
interface ConfigInterceptor { | |
beforeInterceptors?: BeforeInterceptors[]; | |
afterInterceptors?: AfterInterceptors[]; | |
} | |
/** | |
* Get request | |
* @param url | |
* @param config | |
*/ | |
export function getRequest<T>(url: string, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return executeRequest({url, method: 'GET', ...config}); | |
} | |
/** | |
* Post request | |
* @param url | |
* @param body | |
* @param config | |
*/ | |
export function postRequest<T>(url: string, body: any, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return executeRequest({url, body, method: 'POST', ...config}); | |
} | |
/** | |
* Post request | |
* @param url | |
* @param body | |
* @param config | |
*/ | |
export function putRequest<T>(url: string, body: any, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return executeRequest({url, method: 'PUT', ...config}); | |
} | |
/** | |
* Put request | |
* @param url | |
* @param body | |
* @param config | |
*/ | |
export function patchRequest<T>(url: string, body: any, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return executeRequest({url, method: 'PATCH', ...config}); | |
} | |
/** | |
* Delete request | |
* @param url | |
* @param config | |
*/ | |
export function deleteRequest<T>(url: string, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return executeRequest({url, method: 'DELETE', ...config}); | |
} | |
export const configInterceptors = (config: ConfigInterceptor) => { | |
(config.beforeInterceptors || []).forEach(interceptor => BEFORE_INTERCEPTORS.push(interceptor)); | |
(config.afterInterceptors || []).forEach(interceptor => AFTER_INTERCEPTORS.push(interceptor)); | |
} | |
function executeRequest<T>(config: AjaxConfig): Observable<AjaxResponse<T>> { | |
const beforeInterceptors: OperatorFunction<AjaxConfig, AjaxConfig>[] = BEFORE_INTERCEPTORS.map(interceptor => switchMap((requestConfig: AjaxConfig) => { | |
const result = interceptor(requestConfig); | |
if (result instanceof Promise) { | |
return from(result); | |
} | |
if (result instanceof Observable) { | |
return result; | |
} | |
return of(result); | |
})); | |
let execution: Observable<AjaxConfig> | Observable<AjaxResponse<T>> = of(config); | |
for (const interceptor of beforeInterceptors) { | |
execution = execution.pipe(interceptor); | |
} | |
execution = execution | |
.pipe<AjaxResponse<T>>(switchMap((requestConfig) => ajax<T>(requestConfig))); | |
const afterInterceptors: OperatorFunction<AjaxResponse<T>, AjaxResponse<T>>[] = AFTER_INTERCEPTORS.map(interceptor => switchMap((response: AjaxResponse<T>) => { | |
const result = interceptor(response); | |
if (result instanceof Promise) { | |
return from(result); | |
} | |
if (result instanceof Observable) { | |
return result; | |
} | |
return of(result); | |
})); | |
for (const interceptor of afterInterceptors) { | |
execution = execution.pipe(interceptor); | |
} | |
return execution; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ajax, AjaxConfig, AjaxResponse } from 'rxjs/ajax'; | |
import { from, map, Observable, of, OperatorFunction, switchMap } from 'rxjs'; | |
export type BeforeInterceptors = (config: AjaxConfig) => Promise<AjaxConfig> | AjaxConfig | Observable<AjaxConfig>; | |
export type AfterInterceptors<T extends any = any> = (response: AjaxResponse<T>) => Observable<AjaxResponse<T>> | AjaxResponse<T> | Promise<AjaxResponse<T>>; | |
export class HttpService { | |
protected ajaxInstance; | |
constructor(protected beforeInterceptors: BeforeInterceptors[] = [], protected afterInterceptors: AfterInterceptors[] = [] ) { | |
this.ajaxInstance = ajax; | |
} | |
/** | |
* Get request | |
* @param url | |
* @param config | |
*/ | |
public get<T>(url: string, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return this.executeRequest({url, method: 'GET', ...config}); | |
} | |
/** | |
* Post request | |
* @param url | |
* @param body | |
* @param config | |
*/ | |
public post<T>(url: string, body: any, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return this.executeRequest({url, body, method: 'POST', ...config}); | |
} | |
/** | |
* Post request | |
* @param url | |
* @param body | |
* @param config | |
*/ | |
public put<T>(url: string, body: any, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return this.executeRequest({url, method: 'PUT', ...config}); | |
} | |
/** | |
* Put request | |
* @param url | |
* @param body | |
* @param config | |
*/ | |
public patch<T>(url: string, body: any, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return this.executeRequest({url, method: 'PATCH', ...config}); | |
} | |
/** | |
* Delete request | |
* @param url | |
* @param config | |
*/ | |
public delete<T>(url: string, config: Omit<AjaxConfig, 'url' | 'body'>): Observable<AjaxResponse<T>> { | |
return this.executeRequest({url, method: 'DELETE', ...config}); | |
} | |
protected executeRequest<T>(config: AjaxConfig): Observable<AjaxResponse<T>> { | |
const beforeInterceptors: OperatorFunction<AjaxConfig, AjaxConfig>[] = this.beforeInterceptors.map(interceptor => switchMap((requestConfig: AjaxConfig) => { | |
const result = interceptor(requestConfig); | |
if (result instanceof Promise) { | |
return from(result); | |
} | |
if (result instanceof Observable) { | |
return result; | |
} | |
return of(result); | |
})); | |
let execution: Observable<AjaxConfig> | Observable<AjaxResponse<T>> = of(config); | |
for (const interceptor of beforeInterceptors) { | |
execution = execution.pipe(interceptor); | |
} | |
execution = execution | |
.pipe<AjaxResponse<T>>(switchMap((requestConfig) => this.ajaxInstance<T>(requestConfig))); | |
const afterInterceptors: OperatorFunction<AjaxResponse<T>, AjaxResponse<T>>[] = this.afterInterceptors.map(interceptor => switchMap((response: AjaxResponse<T>) => { | |
const result = interceptor(response); | |
if (result instanceof Promise) { | |
return from(result); | |
} | |
if (result instanceof Observable) { | |
return result; | |
} | |
return of(result); | |
})); | |
for (const interceptor of afterInterceptors) { | |
execution = execution.pipe(interceptor); | |
} | |
return execution; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment