Skip to content

Commit 7b5823c

Browse files
committed
- Added cancelable concept that works (rough)
1 parent c6d9f56 commit 7b5823c

33 files changed

+684
-324
lines changed
Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,73 @@
1-
export class CancelablePromise<T> extends Promise<T> {
1+
export class CancelablePromise<T> implements Promise<T> {
2+
readonly [Symbol.toStringTag]: string;
23

3-
private readonly _cancel: (reason?: any) => void;
4+
private _isPending: boolean = true;
5+
private _isCanceled: boolean = false;
6+
private _promise: Promise<T>;
7+
private _resolve?: (value: T | PromiseLike<T>) => void;
8+
private _reject?: (reason?: unknown) => void;
9+
private _cancelHandler?: () => void;
410

5-
constructor(executor: (
6-
resolve: (value: T | PromiseLike<T>) => void,
7-
reject: () => void
8-
cancel: () => void
9-
) => void) {
10-
super(executor);
11+
constructor(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: unknown) => void, onCancel: (cancelHandler: () => void) => void) => void) {
12+
this._promise = new Promise<T>((resolve, reject) => {
13+
this._resolve = resolve;
14+
this._reject = reject;
15+
16+
const onResolve = (value: T | PromiseLike<T>): void => {
17+
if (!this._isCanceled && this._resolve) {
18+
this._isPending = false;
19+
this._resolve(value);
20+
}
21+
};
22+
23+
const onReject = (reason?: unknown): void => {
24+
if (this._reject) {
25+
this._isPending = false;
26+
this._reject(reason);
27+
}
28+
};
29+
30+
const onCancel = (cancelHandler: () => void): void => {
31+
if (this._isPending) {
32+
this._cancelHandler = cancelHandler;
33+
}
34+
};
35+
36+
return executor(onResolve, onReject, onCancel);
37+
});
38+
}
39+
40+
public then<TResult1 = T, TResult2 = never>(
41+
onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
42+
onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
43+
): Promise<TResult1 | TResult2> {
44+
return this._promise.then(onFulfilled, onRejected);
45+
}
46+
47+
public catch<TResult = never>(onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult> {
48+
return this._promise.catch(onRejected);
49+
}
50+
51+
public finally(onFinally?: (() => void) | undefined | null): Promise<T> {
52+
return this._promise.finally(onFinally);
1153
}
1254

1355
public cancel() {
14-
//
56+
if (!this._isPending || this._isCanceled) {
57+
return;
58+
}
59+
this._isCanceled = true;
60+
if (this._cancelHandler && this._reject) {
61+
try {
62+
this._cancelHandler();
63+
} catch (error) {
64+
this._reject(error);
65+
return;
66+
}
67+
}
68+
}
69+
70+
public get isCanceled(): boolean {
71+
return this._isCanceled;
1572
}
1673
}

src/templates/core/fetch/getRequestBody.hbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined {
22
if (options.formData) {
33
return getFormData(options.formData);
44
}
5+
56
if (options.body) {
67
if (isString(options.body) || isBlob(options.body)) {
78
return options.body;
89
} else {
910
return JSON.stringify(options.body);
1011
}
1112
}
13+
1214
return undefined;
1315
}

src/templates/core/fetch/getResponseBody.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ async function getResponseBody(response: Response): Promise<any> {
1212
} catch (error) {
1313
console.error(error);
1414
}
15+
1516
return null;
1617
}

src/templates/core/fetch/getResponseHeader.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ function getResponseHeader(response: Response, responseHeader?: string): string
55
return content;
66
}
77
}
8+
89
return null;
910
}

src/templates/core/fetch/request.hbs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,26 @@ import { OpenAPI } from './OpenAPI';
5555
* @throws ApiError
5656
*/
5757
export function request<T>(options: ApiRequestOptions): CancelablePromise<T> {
58-
return new CancelablePromise((resolve, reject, cancel) => {
59-
const controller = new AbortController();
60-
const url = getUrl(options);
61-
const response = await sendRequest(options, url, controller.signal);
62-
const responseBody = await getResponseBody(response);
63-
const responseHeader = getResponseHeader(response, options.responseHeader);
64-
65-
const result: ApiResult = {
66-
url,
67-
ok: response.ok,
68-
status: response.status,
69-
statusText: response.statusText,
70-
body: responseHeader || responseBody,
71-
};
72-
73-
catchErrors(options, result);
58+
return new CancelablePromise(async (resolve, reject, onCancel) => {
59+
try {
60+
const url = getUrl(options);
61+
const response = await sendRequest(options, url, onCancel);
62+
const responseBody = await getResponseBody(response);
63+
const responseHeader = getResponseHeader(response, options.responseHeader);
64+
65+
const result: ApiResult = {
66+
url,
67+
ok: response.ok,
68+
status: response.status,
69+
statusText: response.statusText,
70+
body: responseHeader || responseBody,
71+
};
72+
73+
catchErrors(options, result);
74+
75+
resolve(result.body);
76+
} catch (error) {
77+
reject(error);
78+
}
7479
});
7580
}
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
async function sendRequest(options: ApiRequestOptions, url: string, signal: AbortSignal): Promise<Response> {
1+
async function sendRequest(options: ApiRequestOptions, url: string, onCancel: (cancelHandler: () => void) => void): Promise<Response> {
2+
const controller = new AbortController();
3+
24
const request: RequestInit = {
35
method: options.method,
46
headers: await getHeaders(options),
57
body: getRequestBody(options),
6-
signal,
8+
signal: controller.signal,
79
};
10+
811
if (OpenAPI.WITH_CREDENTIALS) {
912
request.credentials = 'include';
1013
}
14+
15+
onCancel(() => controller.abort());
16+
1117
return await fetch(url, request);
1218
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
function getFormData(params: Record<string, any>): FormData {
22
const formData = new FormData();
3+
34
Object.keys(params).forEach(key => {
45
const value = params[key];
56
if (isDefined(value)) {
67
formData.append(key, value);
78
}
89
});
10+
911
return formData;
1012
}

src/templates/core/functions/getQueryString.hbs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
function getQueryString(params: Record<string, any>): string {
22
const qs: string[] = [];
3+
34
Object.keys(params).forEach(key => {
45
const value = params[key];
56
if (isDefined(value)) {
@@ -12,8 +13,10 @@ function getQueryString(params: Record<string, any>): string {
1213
}
1314
}
1415
});
16+
1517
if (qs.length > 0) {
1618
return `?${qs.join('&')}`;
1719
}
20+
1821
return '';
1922
}

src/templates/core/functions/getUrl.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ function getUrl(options: ApiRequestOptions): string {
55
if (options.query) {
66
return `${url}${getQueryString(options.query)}`;
77
}
8+
89
return url;
910
}

src/templates/core/node/getRequestBody.hbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined {
22
if (options.formData) {
33
return getFormData(options.formData);
44
}
5+
56
if (options.body) {
67
if (isString(options.body) || isBinary(options.body)) {
78
return options.body;
89
} else {
910
return JSON.stringify(options.body);
1011
}
1112
}
13+
1214
return undefined;
1315
}

0 commit comments

Comments
 (0)