Feature/add default template parameters to web response (#24)
* Add Default template parameters to WebResponse
This commit is contained in:
Родитель
f422577529
Коммит
7336a53474
|
@ -8,8 +8,12 @@
|
||||||
|
|
||||||
import _ = require('lodash');
|
import _ = require('lodash');
|
||||||
import SyncTasks = require('synctasks');
|
import SyncTasks = require('synctasks');
|
||||||
|
import {
|
||||||
import { SimpleWebRequest, WebRequestOptions, WebResponse } from './SimpleWebRequest';
|
WebRequestOptions,
|
||||||
|
WebResponse,
|
||||||
|
Headers,
|
||||||
|
SimpleWebRequest,
|
||||||
|
} from './SimpleWebRequest';
|
||||||
|
|
||||||
export type HttpAction = 'POST'|'GET'|'PUT'|'DELETE'|'PATCH';
|
export type HttpAction = 'POST'|'GET'|'PUT'|'DELETE'|'PATCH';
|
||||||
|
|
||||||
|
@ -20,12 +24,10 @@ export interface ApiCallOptions extends WebRequestOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ETagResponse<T> {
|
export interface ETagResponse<T> {
|
||||||
// Indicates whether the provided ETag matched. If true,
|
// Indicates whether the provided ETag matched. If true, the response is undefined.
|
||||||
// the response is undefined.
|
|
||||||
eTagMatched?: boolean;
|
eTagMatched?: boolean;
|
||||||
|
|
||||||
// If the ETag didn't match, the response contains the updated
|
// If the ETag didn't match, the response contains the updated information.
|
||||||
// information.
|
|
||||||
response?: T;
|
response?: T;
|
||||||
|
|
||||||
// The updated ETag value.
|
// The updated ETag value.
|
||||||
|
@ -33,12 +35,13 @@ export interface ETagResponse<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GenericRestClient {
|
export class GenericRestClient {
|
||||||
|
|
||||||
protected _endpointUrl: string;
|
protected _endpointUrl: string;
|
||||||
|
|
||||||
protected _defaultOptions: ApiCallOptions = {
|
protected _defaultOptions: ApiCallOptions = {
|
||||||
|
excludeEndpointUrl: false,
|
||||||
withCredentials: false,
|
withCredentials: false,
|
||||||
retries: 0,
|
retries: 0,
|
||||||
excludeEndpointUrl: false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(endpointUrl: string) {
|
constructor(endpointUrl: string) {
|
||||||
|
@ -46,22 +49,23 @@ export class GenericRestClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _performApiCall<T>(apiPath: string, action: HttpAction, objToPost: any, givenOptions?: ApiCallOptions)
|
protected _performApiCall<T>(apiPath: string, action: HttpAction, objToPost: any, givenOptions?: ApiCallOptions)
|
||||||
: SyncTasks.Promise<WebResponse<T>> {
|
: SyncTasks.Promise<WebResponse<T, ApiCallOptions>> {
|
||||||
let options = _.defaults<ApiCallOptions, ApiCallOptions, ApiCallOptions>({}, givenOptions || {}, this._defaultOptions);
|
|
||||||
|
|
||||||
|
let options = _.defaults<ApiCallOptions, ApiCallOptions, ApiCallOptions>({}, givenOptions || {}, this._defaultOptions);
|
||||||
if (objToPost) {
|
if (objToPost) {
|
||||||
options.sendData = objToPost;
|
options.sendData = objToPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
let promise = this._blockRequestUntil(options);
|
const promise = this._blockRequestUntil(options);
|
||||||
if (!promise) {
|
if (!promise) {
|
||||||
return this._performApiCallInternal(apiPath, action, options);
|
return this._performApiCallInternal(apiPath, action, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(() => this._performApiCallInternal(apiPath, action, options));
|
return promise.then(() => this._performApiCallInternal(apiPath, action, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _performApiCallInternal<T>(apiPath: string, action: HttpAction, options: ApiCallOptions)
|
private _performApiCallInternal<T>(apiPath: string, action: HttpAction, options: ApiCallOptions)
|
||||||
: SyncTasks.Promise<WebResponse<T>> {
|
: SyncTasks.Promise<WebResponse<T, ApiCallOptions>> {
|
||||||
|
|
||||||
if (options.eTag) {
|
if (options.eTag) {
|
||||||
if (!options.augmentHeaders) {
|
if (!options.augmentHeaders) {
|
||||||
|
@ -76,14 +80,15 @@ export class GenericRestClient {
|
||||||
|
|
||||||
const finalUrl = options.excludeEndpointUrl ? apiPath : this._endpointUrl + apiPath;
|
const finalUrl = options.excludeEndpointUrl ? apiPath : this._endpointUrl + apiPath;
|
||||||
|
|
||||||
let request = new SimpleWebRequest<T>(action, finalUrl, options, () => this._getHeaders(options));
|
return new SimpleWebRequest<T, ApiCallOptions>(action, finalUrl, options, () => this._getHeaders(options))
|
||||||
return request.start().then(resp => {
|
.start()
|
||||||
this._processSuccessResponse<T>(resp);
|
.then(response => {
|
||||||
return resp;
|
this._processSuccessResponse<T>(response);
|
||||||
|
return response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _getHeaders(options: ApiCallOptions): { [header: string]: string } {
|
protected _getHeaders(options: ApiCallOptions): Headers {
|
||||||
// Virtual function -- No-op by default
|
// Virtual function -- No-op by default
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -95,42 +100,62 @@ export class GenericRestClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override this function to process any generic headers that come down with a successful response
|
// Override this function to process any generic headers that come down with a successful response
|
||||||
protected _processSuccessResponse<T>(resp: WebResponse<T>): void {
|
protected _processSuccessResponse<T>(resp: WebResponse<T, ApiCallOptions>): void {
|
||||||
// No-op by default
|
// No-op by default
|
||||||
}
|
}
|
||||||
|
|
||||||
performApiGet<T>(apiPath: string, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
performApiGet<T>(apiPath: string, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
||||||
return this.performApiGetDetailed<T>(apiPath, options).then(resp => resp.body);
|
return this
|
||||||
|
.performApiGetDetailed<T>(apiPath, options)
|
||||||
|
.then(resp => resp.body);
|
||||||
}
|
}
|
||||||
performApiGetDetailed<T>(apiPath: string, options?: ApiCallOptions): SyncTasks.Promise<WebResponse<T>> {
|
|
||||||
|
performApiGetDetailed<T>(apiPath: string, options?: ApiCallOptions)
|
||||||
|
: SyncTasks.Promise<WebResponse<T, ApiCallOptions>> {
|
||||||
return this._performApiCall<T>(apiPath, 'GET', undefined, options);
|
return this._performApiCall<T>(apiPath, 'GET', undefined, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
performApiPost<T>(apiPath: string, objToPost: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
performApiPost<T>(apiPath: string, objToPost: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
||||||
return this.performApiPostDetailed<T>(apiPath, objToPost, options).then(resp => resp.body);
|
return this
|
||||||
|
.performApiPostDetailed<T>(apiPath, objToPost, options)
|
||||||
|
.then(resp => resp.body);
|
||||||
}
|
}
|
||||||
performApiPostDetailed<T>(apiPath: string, objToPost: any, options?: ApiCallOptions): SyncTasks.Promise<WebResponse<T>> {
|
|
||||||
|
performApiPostDetailed<T>(apiPath: string, objToPost: any, options?: ApiCallOptions)
|
||||||
|
: SyncTasks.Promise<WebResponse<T, ApiCallOptions>> {
|
||||||
return this._performApiCall<T>(apiPath, 'POST', objToPost, options);
|
return this._performApiCall<T>(apiPath, 'POST', objToPost, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
performApiPatch<T>(apiPath: string, objToPatch: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
performApiPatch<T>(apiPath: string, objToPatch: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
||||||
return this.performApiPatchDetailed<T>(apiPath, objToPatch, options).then(resp => resp.body);
|
return this
|
||||||
|
.performApiPatchDetailed<T>(apiPath, objToPatch, options)
|
||||||
|
.then(resp => resp.body);
|
||||||
}
|
}
|
||||||
performApiPatchDetailed<T>(apiPath: string, objToPatch: any, options?: ApiCallOptions): SyncTasks.Promise<WebResponse<T>> {
|
|
||||||
|
performApiPatchDetailed<T>(apiPath: string, objToPatch: any, options?: ApiCallOptions)
|
||||||
|
: SyncTasks.Promise<WebResponse<T, ApiCallOptions>> {
|
||||||
return this._performApiCall<T>(apiPath, 'PATCH', objToPatch, options);
|
return this._performApiCall<T>(apiPath, 'PATCH', objToPatch, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
performApiPut<T>(apiPath: string, objToPut: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
performApiPut<T>(apiPath: string, objToPut: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
||||||
return this.performApiPutDetailed<T>(apiPath, objToPut, options).then(resp => resp.body);
|
return this
|
||||||
|
.performApiPutDetailed<T>(apiPath, objToPut, options)
|
||||||
|
.then(resp => resp.body);
|
||||||
}
|
}
|
||||||
performApiPutDetailed<T>(apiPath: string, objToPut: any, options?: ApiCallOptions): SyncTasks.Promise<WebResponse<T>> {
|
|
||||||
|
performApiPutDetailed<T>(apiPath: string, objToPut: any, options?: ApiCallOptions)
|
||||||
|
: SyncTasks.Promise<WebResponse<T, ApiCallOptions>> {
|
||||||
return this._performApiCall<T>(apiPath, 'PUT', objToPut, options);
|
return this._performApiCall<T>(apiPath, 'PUT', objToPut, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
performApiDelete<T>(apiPath: string, objToDelete?: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
performApiDelete<T>(apiPath: string, objToDelete?: any, options?: ApiCallOptions): SyncTasks.Promise<T> {
|
||||||
return this.performApiDeleteDetailed<T>(apiPath, objToDelete, options).then(resp => resp.body);
|
return this
|
||||||
|
.performApiDeleteDetailed<T>(apiPath, objToDelete, options)
|
||||||
|
.then(resp => resp.body);
|
||||||
}
|
}
|
||||||
performApiDeleteDetailed<T>(apiPath: string, objToDelete: any, options?: ApiCallOptions): SyncTasks.Promise<WebResponse<T>> {
|
|
||||||
|
performApiDeleteDetailed<T>(apiPath: string, objToDelete: any, options?: ApiCallOptions)
|
||||||
|
: SyncTasks.Promise<WebResponse<T, ApiCallOptions>> {
|
||||||
return this._performApiCall<T>(apiPath, 'DELETE', objToDelete, options);
|
return this._performApiCall<T>(apiPath, 'DELETE', objToDelete, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,20 @@ import SyncTasks = require('synctasks');
|
||||||
|
|
||||||
import { ExponentialTime } from './ExponentialTime';
|
import { ExponentialTime } from './ExponentialTime';
|
||||||
|
|
||||||
|
export interface Headers {
|
||||||
|
[header: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface WebTransportResponseBase {
|
export interface WebTransportResponseBase {
|
||||||
url: string;
|
url: string;
|
||||||
method: string;
|
method: string;
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
statusText: string|undefined;
|
statusText: string|undefined;
|
||||||
headers: _.Dictionary<string>;
|
headers: Headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebTransportResponse<T> extends WebTransportResponseBase {
|
export interface WebTransportResponse<TBody> extends WebTransportResponseBase {
|
||||||
body: T;
|
body: TBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebTransportErrorResponse extends WebTransportResponseBase {
|
export interface WebTransportErrorResponse extends WebTransportResponseBase {
|
||||||
|
@ -30,19 +34,19 @@ export interface WebTransportErrorResponse extends WebTransportResponseBase {
|
||||||
timedOut: boolean;
|
timedOut: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RestRequestInResponse {
|
export interface RestRequestInResponse<TOptions = WebRequestOptions> {
|
||||||
requestOptions: WebRequestOptions;
|
requestOptions: TOptions;
|
||||||
requestHeaders: _.Dictionary<string>;
|
requestHeaders: Headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebResponseBase extends RestRequestInResponse, WebTransportResponseBase {
|
export interface WebResponseBase<TOptions = WebRequestOptions>
|
||||||
}
|
extends WebTransportResponseBase, RestRequestInResponse<TOptions> {}
|
||||||
|
|
||||||
export interface WebResponse<T> extends RestRequestInResponse, WebTransportResponse<T> {
|
export interface WebErrorResponse<TOptions = WebRequestOptions>
|
||||||
}
|
extends WebTransportErrorResponse, RestRequestInResponse<TOptions> {}
|
||||||
|
|
||||||
export interface WebErrorResponse extends RestRequestInResponse, WebTransportErrorResponse {
|
export interface WebResponse<TBody, TOptions = WebRequestOptions>
|
||||||
}
|
extends WebTransportResponse<TBody>, RestRequestInResponse<TOptions> {}
|
||||||
|
|
||||||
export enum WebRequestPriority {
|
export enum WebRequestPriority {
|
||||||
DontCare = 0,
|
DontCare = 0,
|
||||||
|
@ -77,7 +81,7 @@ export interface NativeBlobFileData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NativeFileData {
|
export interface NativeFileData {
|
||||||
file: NativeBlobFileData | File;
|
file: NativeBlobFileData|File;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface XMLHttpRequestProgressEvent extends ProgressEvent {
|
export interface XMLHttpRequestProgressEvent extends ProgressEvent {
|
||||||
|
@ -100,12 +104,12 @@ export interface WebRequestOptions {
|
||||||
acceptType?: string;
|
acceptType?: string;
|
||||||
contentType?: string;
|
contentType?: string;
|
||||||
sendData?: SendDataType;
|
sendData?: SendDataType;
|
||||||
/* Deprecated: use overrideGetHeaders */ headers?: _.Dictionary<string>;
|
/* Deprecated: use overrideGetHeaders */ headers?: Headers;
|
||||||
|
|
||||||
// Used instead of calling getHeaders.
|
// Used instead of calling getHeaders.
|
||||||
overrideGetHeaders?: _.Dictionary<string>;
|
overrideGetHeaders?: Headers;
|
||||||
// Overrides all other headers.
|
// Overrides all other headers.
|
||||||
augmentHeaders?: _.Dictionary<string>;
|
augmentHeaders?: Headers;
|
||||||
|
|
||||||
onProgress?: (progressEvent: XMLHttpRequestProgressEvent) => void;
|
onProgress?: (progressEvent: XMLHttpRequestProgressEvent) => void;
|
||||||
|
|
||||||
|
@ -125,7 +129,7 @@ function isFormDataContentType(ct: string) {
|
||||||
return ct && ct.indexOf('multipart/form-data') === 0;
|
return ct && ct.indexOf('multipart/form-data') === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export let DefaultOptions: WebRequestOptions = {
|
export const DefaultOptions: WebRequestOptions = {
|
||||||
priority: WebRequestPriority.Normal
|
priority: WebRequestPriority.Normal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -147,7 +151,8 @@ export let SimpleWebRequestOptions: ISimpleWebRequestOptions = {
|
||||||
|
|
||||||
export function DefaultErrorHandler(webRequest: SimpleWebRequestBase, errResp: WebTransportErrorResponse) {
|
export function DefaultErrorHandler(webRequest: SimpleWebRequestBase, errResp: WebTransportErrorResponse) {
|
||||||
if (errResp.canceled || !errResp.statusCode || errResp.statusCode >= 400 && errResp.statusCode < 600) {
|
if (errResp.canceled || !errResp.statusCode || errResp.statusCode >= 400 && errResp.statusCode < 600) {
|
||||||
// Fail canceled/0/4xx/5xx requests immediately. These are permenent failures, and shouldn't have retry logic applied to them.
|
// Fail canceled/0/4xx/5xx requests immediately.
|
||||||
|
// These are permenent failures, and shouldn't have retry logic applied to them.
|
||||||
return ErrorHandlingType.DoNotRetry;
|
return ErrorHandlingType.DoNotRetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,11 +178,11 @@ let executingList: SimpleWebRequestBase[] = [];
|
||||||
let onLoadErrorSupportStatus = FeatureSupportStatus.Unknown;
|
let onLoadErrorSupportStatus = FeatureSupportStatus.Unknown;
|
||||||
let timeoutSupportStatus = FeatureSupportStatus.Unknown;
|
let timeoutSupportStatus = FeatureSupportStatus.Unknown;
|
||||||
|
|
||||||
export abstract class SimpleWebRequestBase {
|
export abstract class SimpleWebRequestBase<TOptions extends WebRequestOptions = WebRequestOptions> {
|
||||||
protected _xhr: XMLHttpRequest|undefined;
|
protected _xhr: XMLHttpRequest|undefined;
|
||||||
protected _xhrRequestHeaders: _.Dictionary<string>|undefined;
|
protected _xhrRequestHeaders: Headers|undefined;
|
||||||
protected _requestTimeoutTimer: number|undefined;
|
protected _requestTimeoutTimer: number|undefined;
|
||||||
protected _options: WebRequestOptions;
|
protected _options: TOptions;
|
||||||
|
|
||||||
protected _aborted = false;
|
protected _aborted = false;
|
||||||
protected _timedOut = false;
|
protected _timedOut = false;
|
||||||
|
@ -191,8 +196,9 @@ export abstract class SimpleWebRequestBase {
|
||||||
protected _retryTimer: number|undefined;
|
protected _retryTimer: number|undefined;
|
||||||
protected _retryExponentialTime = new ExponentialTime(1000, 300000);
|
protected _retryExponentialTime = new ExponentialTime(1000, 300000);
|
||||||
|
|
||||||
constructor(protected _action: string, protected _url: string, options: WebRequestOptions,
|
constructor(protected _action: string,
|
||||||
protected _getHeaders?: () => _.Dictionary<string>) {
|
protected _url: string, options: TOptions,
|
||||||
|
protected _getHeaders?: () => Headers) {
|
||||||
this._options = _.defaults(options, DefaultOptions);
|
this._options = _.defaults(options, DefaultOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,8 +426,8 @@ export abstract class SimpleWebRequestBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getRequestHeaders(): { [header: string]: string } {
|
getRequestHeaders(): Headers {
|
||||||
let headers: { [header: string]: string } = {};
|
let headers: Headers = {};
|
||||||
|
|
||||||
if (this._getHeaders && !this._options.overrideGetHeaders && !this._options.headers) {
|
if (this._getHeaders && !this._options.overrideGetHeaders && !this._options.headers) {
|
||||||
headers = _.extend(headers, this._getHeaders());
|
headers = _.extend(headers, this._getHeaders());
|
||||||
|
@ -488,6 +494,7 @@ export abstract class SimpleWebRequestBase {
|
||||||
// Throw it on the queue
|
// Throw it on the queue
|
||||||
const index = _.findIndex(requestQueue, request =>
|
const index = _.findIndex(requestQueue, request =>
|
||||||
request.getPriority() < (this._options.priority || WebRequestPriority.DontCare));
|
request.getPriority() < (this._options.priority || WebRequestPriority.DontCare));
|
||||||
|
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
requestQueue.splice(index, 0, this);
|
requestQueue.splice(index, 0, this);
|
||||||
} else {
|
} else {
|
||||||
|
@ -513,10 +520,11 @@ export abstract class SimpleWebRequestBase {
|
||||||
protected abstract _respond(errorStatusText?: string): void;
|
protected abstract _respond(errorStatusText?: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SimpleWebRequest<T> extends SimpleWebRequestBase {
|
export class SimpleWebRequest<TBody, TOptions extends WebRequestOptions = WebRequestOptions> extends SimpleWebRequestBase<TOptions> {
|
||||||
private _deferred: SyncTasks.Deferred<WebResponse<T>>;
|
|
||||||
|
|
||||||
constructor(action: string, url: string, options: WebRequestOptions, getHeaders?: () => _.Dictionary<string>) {
|
private _deferred: SyncTasks.Deferred<WebResponse<TBody, TOptions>>;
|
||||||
|
|
||||||
|
constructor(action: string, url: string, options: TOptions, getHeaders?: () => Headers) {
|
||||||
super(action, url, options, getHeaders);
|
super(action, url, options, getHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,13 +560,13 @@ export class SimpleWebRequest<T> extends SimpleWebRequestBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start(): SyncTasks.Promise<WebResponse<T>> {
|
start(): SyncTasks.Promise<WebResponse<TBody, TOptions>> {
|
||||||
if (this._deferred) {
|
if (this._deferred) {
|
||||||
assert.ok(false, 'WebRequest already started');
|
assert.ok(false, 'WebRequest already started');
|
||||||
return SyncTasks.Rejected('WebRequest already started');
|
return SyncTasks.Rejected('WebRequest already started');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._deferred = SyncTasks.Defer<WebResponse<T>>();
|
this._deferred = SyncTasks.Defer<WebResponse<TBody, TOptions>>();
|
||||||
this._deferred.onCancel(() => {
|
this._deferred.onCancel(() => {
|
||||||
// Abort the XHR -- this should chain through to the fail case on readystatechange
|
// Abort the XHR -- this should chain through to the fail case on readystatechange
|
||||||
this.abort();
|
this.abort();
|
||||||
|
@ -611,7 +619,7 @@ export class SimpleWebRequest<T> extends SimpleWebRequestBase {
|
||||||
statusText = 'Browser Error - Possible CORS or Connectivity Issue';
|
statusText = 'Browser Error - Possible CORS or Connectivity Issue';
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers: _.Dictionary<string> = {};
|
let headers: Headers = {};
|
||||||
let body: any;
|
let body: any;
|
||||||
|
|
||||||
// Build the response info
|
// Build the response info
|
||||||
|
@ -659,7 +667,7 @@ export class SimpleWebRequest<T> extends SimpleWebRequestBase {
|
||||||
|
|
||||||
if (this._xhr && this._xhr.readyState === 4 && ((statusCode >= 200 && statusCode < 300) || statusCode === 304)) {
|
if (this._xhr && this._xhr.readyState === 4 && ((statusCode >= 200 && statusCode < 300) || statusCode === 304)) {
|
||||||
// Happy path!
|
// Happy path!
|
||||||
const resp: WebResponse<T> = {
|
const resp: WebResponse<TBody, TOptions> = {
|
||||||
url: this._xhr.responseURL || this._url,
|
url: this._xhr.responseURL || this._url,
|
||||||
method: this._action,
|
method: this._action,
|
||||||
requestOptions: this._options,
|
requestOptions: this._options,
|
||||||
|
@ -667,11 +675,12 @@ export class SimpleWebRequest<T> extends SimpleWebRequestBase {
|
||||||
statusCode: statusCode,
|
statusCode: statusCode,
|
||||||
statusText: statusText,
|
statusText: statusText,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: body as T
|
body: body as TBody,
|
||||||
};
|
};
|
||||||
|
|
||||||
this._deferred.resolve(resp);
|
this._deferred.resolve(resp);
|
||||||
} else {
|
} else {
|
||||||
let errResp: WebErrorResponse = {
|
let errResp: WebErrorResponse<TOptions> = {
|
||||||
url: (this._xhr ? this._xhr.responseURL : undefined) || this._url,
|
url: (this._xhr ? this._xhr.responseURL : undefined) || this._url,
|
||||||
method: this._action,
|
method: this._action,
|
||||||
requestOptions: this._options,
|
requestOptions: this._options,
|
||||||
|
@ -681,7 +690,7 @@ export class SimpleWebRequest<T> extends SimpleWebRequestBase {
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: body,
|
body: body,
|
||||||
canceled: this._aborted,
|
canceled: this._aborted,
|
||||||
timedOut: this._timedOut
|
timedOut: this._timedOut,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this._options.augmentErrorResponse) {
|
if (this._options.augmentErrorResponse) {
|
||||||
|
@ -689,8 +698,9 @@ export class SimpleWebRequest<T> extends SimpleWebRequestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Policy-adaptable failure
|
// Policy-adaptable failure
|
||||||
const handleResponse = this._options.customErrorHandler ? this._options.customErrorHandler(this, errResp) :
|
const handleResponse = this._options.customErrorHandler
|
||||||
DefaultErrorHandler(this, errResp);
|
? this._options.customErrorHandler(this, errResp)
|
||||||
|
: DefaultErrorHandler(this, errResp);
|
||||||
|
|
||||||
const retry = handleResponse !== ErrorHandlingType.DoNotRetry && (
|
const retry = handleResponse !== ErrorHandlingType.DoNotRetry && (
|
||||||
(this._options.retries && this._options.retries > 0) ||
|
(this._options.retries && this._options.retries > 0) ||
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
"forceConsistentCasingInFileNames": true
|
"forceConsistentCasingInFileNames": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"filesGlob": [
|
"include": [
|
||||||
"src/**/*{ts,tsx}"
|
"src/**/*"
|
||||||
],
|
],
|
||||||
|
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"forin": true,
|
"forin": true,
|
||||||
"indent": [true, "spaces"],
|
"indent": [true, "spaces"],
|
||||||
"label-position": true,
|
"label-position": true,
|
||||||
"max-line-length": [ true, 140 ],
|
"max-line-length": [true, 140],
|
||||||
"no-arg": true,
|
"no-arg": true,
|
||||||
"no-bitwise": false,
|
"no-bitwise": false,
|
||||||
"no-console": [true,
|
"no-console": [true,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче