Skip to content

Commit

Permalink
refactor: improve cancelled event
Browse files Browse the repository at this point in the history
  • Loading branch information
askuzminov committed Aug 18, 2021
1 parent 8b00816 commit 1d3c090
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 21 deletions.
65 changes: 44 additions & 21 deletions src/http/http.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isFunction, isNumber, isObject, isPresent, isString, isText } from '@whisklabs/typeguards';
import { isFunction, isObject, isPresent, isString, isText } from '@whisklabs/typeguards';

import { Decode, Encode } from '../binary';
import { Field, FieldGet, Service, ServiceRequest, ServiceResponse } from '../types';
Expand All @@ -7,7 +7,7 @@ import { maskWrap } from './mask';
import { Chunk, ChunkType, chunkParse } from './parser';
import { StatusCode, fromHttpStatus } from './status';
import { Cancel, ConfigGRPC, GError, GOutput, GRPC, LocalGRPC } from './types';
import { GRPC_MESSAGE, GRPC_STATUS, encodeRequest, safeJSON, toInt8 } from './utils';
import { GRPC_MESSAGE, GRPC_STATUS, bufToString, encodeRequest, safeJSON, toInt8 } from './utils';

export const grpcCancel = (): Cancel => {
const CancelFn = (() => {
Expand Down Expand Up @@ -46,6 +46,9 @@ export const grpcHTTP = <Meta = unknown>({

const method = `${server}/${field.name}`;
const xhr = new XMLHttpRequest();

xhr.timeout = timeout ?? timeoutConfig ?? 0;

const abortXHR = () => xhr.abort();

if (isPresent(cancel)) {
Expand All @@ -70,16 +73,6 @@ export const grpcHTTP = <Meta = unknown>({

// eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor
return new Promise<GOutput<ServiceResponse<Service<T, K>>>>(async callback => {
const time = timeout ?? timeoutConfig;

if (isNumber(time) && time > 0) {
setTimeout(() => {
callback({ success: false, error: { message: 'timeout', data: time } });
abortXHR();
tmCancel();
}, time);
}

xhr.open('POST', method);

xhr.withCredentials = credentials;
Expand All @@ -95,22 +88,52 @@ export const grpcHTTP = <Meta = unknown>({
xhr.setRequestHeader('x-user-agent', 'grpc-web-ts/1.0');

if (isFunction(onDownload)) {
xhr.onprogress = onDownload;
xhr.addEventListener('progress', onDownload);
}

if (isFunction(onUpload) && isObject(xhr.upload)) {
xhr.upload.onprogress = onUpload;
xhr.upload.addEventListener('progress', onUpload);
}

xhr.onreadystatechange = function onready() {
if (xhr.readyState !== 4) {
return undefined;
}
xhr.addEventListener('timeout', () => {
tmCancel();
callback({ success: false, error: { message: 'timeout', data: xhr.timeout } });
});

xhr.addEventListener('abort', () => {
tmCancel();
callback({
success: false,
error: { message: 'cancelled', httpStatus: xhr.status, grpcCode: StatusCode.CANCELLED },
});
});

if (xhr.status !== 0 && xhr.status !== 200) {
return callback({ success: false, error: { message: 'XHR wrong status', httpStatus: xhr.status } });
xhr.addEventListener('error', () => {
tmCancel();
callback({
success: false,
error: {
message: 'XHR error',
data: bufToString(xhr),
httpStatus: xhr.status,
grpcCode: fromHttpStatus(xhr.status),
},
});
});

xhr.addEventListener('load', function onready() {
tmCancel();

if (xhr.status < 200 || xhr.status >= 300) {
return callback({
success: false,
error: {
message: 'XHR wrong status',
data: bufToString(xhr),
httpStatus: xhr.status,
grpcCode: fromHttpStatus(xhr.status),
},
});
}

const byteSource = toInt8(xhr);
Expand Down Expand Up @@ -177,7 +200,7 @@ export const grpcHTTP = <Meta = unknown>({
});
}
}
};
});

if (isFunction(transformRequest)) {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
Expand Down
1 change: 1 addition & 0 deletions src/http/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export enum StatusCode {
}

const codes: Record<number, StatusCode> = {
0: StatusCode.ABORTED,
200: StatusCode.OK,
400: StatusCode.INVALID_ARGUMENT,
401: StatusCode.UNAUTHENTICATED,
Expand Down
10 changes: 10 additions & 0 deletions src/http/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isArray, isArrayBuffer, isDate, isObject, isPresent } from '@whisklabs/typeguards';

import { readUtf8 } from '../binary/utf8';
import { GError, GOutput } from './types';

export const HEADER_SIZE = 5;
Expand Down Expand Up @@ -36,6 +37,15 @@ export function toInt8(xhr: XMLHttpRequest) {
}
}

export function bufToString(xhr: XMLHttpRequest): string {
try {
return xhr.responseText;
} catch {
const buf = toInt8(xhr);
return buf === false ? '' : readUtf8(buf, 0, buf.byteLength);
}
}

export const safeJSON = (data: string) => {
try {
return JSON.parse(data) as unknown;
Expand Down

0 comments on commit 1d3c090

Please sign in to comment.