Skip to content

Commit

Permalink
Fix/catch reject from fetch (#95)
Browse files Browse the repository at this point in the history
* feat: catch reject from fetch

* feat: add property to ResponseError
  • Loading branch information
chenjsh36 authored Dec 24, 2019
1 parent b52f2ea commit fb0137d
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 9 deletions.
20 changes: 16 additions & 4 deletions src/middleware/parseResponse.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { safeJsonParse, readerGBK, ResponseError, getEnv } from '../utils';
import { safeJsonParse, readerGBK, ResponseError, getEnv, RequestError } from '../utils';

export default function parseResponseMiddleware(ctx, next) {
let copy;
Expand Down Expand Up @@ -37,7 +37,7 @@ export default function parseResponseMiddleware(ctx, next) {
.then(readerGBK)
.then(d => safeJsonParse(d, false, copy, req));
} catch (e) {
throw new ResponseError(copy, e.message, null, req);
throw new ResponseError(copy, e.message, null, req, 'ParseError');
}
} else if (responseType === 'json') {
return res.text().then(d => safeJsonParse(d, throwErrIfParseFail, copy, req));
Expand All @@ -46,7 +46,7 @@ export default function parseResponseMiddleware(ctx, next) {
// 其他如text, blob, arrayBuffer, formData
return res[responseType]();
} catch (e) {
throw new ResponseError(copy, 'responseType not support', null, req);
throw new ResponseError(copy, 'responseType not support', null, req, 'ParseError');
}
})
.then(body => {
Expand All @@ -66,6 +66,18 @@ export default function parseResponseMiddleware(ctx, next) {
ctx.res = body;
return;
}
throw new ResponseError(copy, 'http error', body, req);
throw new ResponseError(copy, 'http error', body, req, 'HttpError');
})
.catch(e => {
if (e instanceof RequestError || e instanceof ResponseError) {
throw e;
}
// 对未知错误进行处理
const { req, res } = ctx;
e.request = req;
e.response = res;
e.type = e.name;
e.data = undefined;
throw e;
});
}
10 changes: 6 additions & 4 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,25 @@ export class MapCache {
* 请求异常
*/
export class RequestError extends Error {
constructor(text, request) {
constructor(text, request, type = 'RequestError') {
super(text);
this.name = 'RequestError';
this.request = request;
this.type = type;
}
}

/**
* 响应异常
*/
export class ResponseError extends Error {
constructor(response, text, data, request) {
constructor(response, text, data, request, type = 'ResponseError') {
super(text || response.statusText);
this.name = 'ResponseError';
this.data = data;
this.response = response;
this.request = request;
this.type = type;
}
}

Expand All @@ -97,7 +99,7 @@ export function safeJsonParse(data, throwErrIfParseFail = false, response = null
return JSON.parse(data);
} catch (e) {
if (throwErrIfParseFail) {
throw new ResponseError(response, 'JSON.parse fail', data, request);
throw new ResponseError(response, 'JSON.parse fail', data, request, 'ParseError');
}
} // eslint-disable-line no-empty
return data;
Expand All @@ -106,7 +108,7 @@ export function safeJsonParse(data, throwErrIfParseFail = false, response = null
export function timeout2Throw(msec, request) {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new RequestError(`timeout of ${msec}ms exceeded`, request));
reject(new RequestError(`timeout of ${msec}ms exceeded`, request, 'Timeout'));
}, msec);
});
}
Expand Down
41 changes: 41 additions & 0 deletions test/errorHandler.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import createTestServer from 'create-test-server';
import request, { extend, Onion, fetch } from '../src/index';

const debug = require('debug')('afx-request:test');

const writeData = (data, res) => {
res.setHeader('access-control-allow-origin', '*');
res.send(data);
};

describe('error handle', () => {
let server;
beforeAll(async () => {
server = await createTestServer();
});
afterAll(() => {
server.close();
});

const prefix = api => `${server.url}${api}`;

it('should catch fetch error and get reponse', async done => {
server.get('/test/reject/302', (req, res) => {
res.setHeader('access-control-allow-origin', '*');
res.status(302);
res.setHeader({ location: 'https://www.baidu.com' });
res.send({ errorMsg: 'error response', errorCode: 'B000' });
});

const req = extend({});

try {
const res = await req(prefix('/test/reject/302'));
} catch (e) {
expect(e.message).toBe('http error');
expect(e.type).toBe('HttpError');
expect(e.response.headers.get('Content-Type')).toBe('text/html; charset=utf-8');
done();
}
});
});
4 changes: 3 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface ResponseError<D = any> extends Error {
url: string;
options: RequestOptionsInit;
};
type: string;
}
/**
* 增加的参数
Expand Down Expand Up @@ -153,6 +154,7 @@ export interface CancelTokenSource {
}

declare var request: RequestMethod;
declare var fetch: RequestMethod;

export declare var fetch: RequestMethod;

export default request;

0 comments on commit fb0137d

Please sign in to comment.