Skip to content

Commit b523936

Browse files
authored
refactor: optimize the way to generate service (#27)
1 parent f675bbb commit b523936

File tree

5 files changed

+147
-169
lines changed

5 files changed

+147
-169
lines changed

src/__tests__/index.test.tsx

Lines changed: 0 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ describe('useRequest', () => {
2828
fetchMock.get(successApi, { data: 'success' });
2929
fetchMock.get(failApi, 404);
3030

31-
const unknownService = 1;
32-
const serviceWillReturnString = () => successApi;
33-
const serviceWillReturnObject = () => ({ url: successApi });
34-
const serviceWillReturnUnknown = () => unknownService;
35-
3631
const originalError = console.error;
3732
beforeEach(() => {
3833
console.error = jest.fn();
@@ -55,120 +50,6 @@ describe('useRequest', () => {
5550
expect(useRequest).toBeDefined();
5651
});
5752

58-
test('should use string service', async () => {
59-
const wrapper = shallowMount(
60-
defineComponent({
61-
setup() {
62-
const { data } = useRequest<{ data: string }>(successApi);
63-
return () => <button>{`${data.value?.data}`}</button>;
64-
},
65-
}),
66-
);
67-
expect(wrapper.text()).toBe('undefined');
68-
await waitForTime(1000);
69-
expect(wrapper.text()).toBe('success');
70-
});
71-
72-
test('should throw error when service error', async () => {
73-
const wrapper = shallowMount(
74-
defineComponent({
75-
setup() {
76-
const { error } = useRequest(failApi);
77-
return () => <button>{`${error.value?.message}`}</button>;
78-
},
79-
}),
80-
);
81-
expect(wrapper.text()).toBe('undefined');
82-
await waitForTime(1000);
83-
expect(wrapper.text()).toBe('Not Found');
84-
});
85-
86-
test('should use object service', async () => {
87-
const wrapper = shallowMount(
88-
defineComponent({
89-
setup() {
90-
const { data } = useRequest<{ data: string }>({
91-
test: 'value',
92-
url: successApi,
93-
});
94-
return () => <button>{`${data.value?.data}`}</button>;
95-
},
96-
}),
97-
);
98-
expect(wrapper.text()).toBe('undefined');
99-
await waitForTime(1000);
100-
expect(wrapper.text()).toBe('success');
101-
});
102-
103-
test('should use function service that will return string', async () => {
104-
const wrapper = shallowMount(
105-
defineComponent({
106-
setup() {
107-
const { data } = useRequest<{ data: string }>(
108-
serviceWillReturnString,
109-
);
110-
return () => <button>{`${data.value?.data}`}</button>;
111-
},
112-
}),
113-
);
114-
expect(wrapper.text()).toBe('undefined');
115-
await waitForTime(1000);
116-
expect(wrapper.text()).toBe('success');
117-
});
118-
119-
test('should use function service that will return object', async () => {
120-
const wrapper = shallowMount(
121-
defineComponent({
122-
setup() {
123-
const { data } = useRequest<{ data: string }>(
124-
serviceWillReturnObject,
125-
);
126-
return () => <button>{`${data.value?.data}`}</button>;
127-
},
128-
}),
129-
);
130-
expect(wrapper.text()).toBe('undefined');
131-
await waitForTime(1000);
132-
expect(wrapper.text()).toBe('success');
133-
});
134-
135-
test('should use function service that will return unknown type', () => {
136-
const fn = jest.fn();
137-
shallowMount(
138-
defineComponent({
139-
setup() {
140-
try {
141-
useRequest(serviceWillReturnUnknown as any);
142-
} catch (error) {
143-
expect(error.message).toBe('Unknown service type');
144-
fn();
145-
}
146-
return () => <div />;
147-
},
148-
}),
149-
);
150-
151-
expect(fn).toHaveBeenCalledTimes(1);
152-
});
153-
154-
test('should throw error when use unknown service', () => {
155-
const fn = jest.fn();
156-
shallowMount(
157-
defineComponent({
158-
setup() {
159-
try {
160-
useRequest(unknownService as any);
161-
} catch (error) {
162-
expect(error.message).toBe('Unknown service type');
163-
fn();
164-
}
165-
return () => <div />;
166-
},
167-
}),
168-
);
169-
expect(fn).toHaveBeenCalledTimes(1);
170-
});
171-
17253
test('should auto run', async () => {
17354
const wrapper = shallowMount(
17455
defineComponent({
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import fetchMock from 'fetch-mock';
2+
import generateService from '../core/utils/generateService';
3+
4+
describe('generateService', () => {
5+
beforeAll(() => {
6+
jest.useFakeTimers('modern');
7+
});
8+
9+
const successApi = 'http://example.com/200';
10+
const failApi = 'http://example.com/404';
11+
// mock fetch
12+
const resultData = { data: 'success' };
13+
fetchMock.get(successApi, resultData);
14+
fetchMock.get(failApi, 404);
15+
16+
const unknownService = 1;
17+
const serviceWillReturnString = () => successApi;
18+
const serviceWillReturnObject = () => ({ url: successApi });
19+
const serviceWillReturnUnknown = () => unknownService;
20+
21+
const originalError = console.error;
22+
beforeEach(() => {
23+
console.error = jest.fn();
24+
});
25+
26+
afterEach(() => {
27+
console.error = originalError;
28+
});
29+
30+
test('should use string service', async () => {
31+
const service = generateService<{ data: string }, any>(successApi);
32+
expect(await service()).toMatchObject(resultData);
33+
});
34+
35+
test('should throw error when service error', async () => {
36+
const fn = jest.fn();
37+
const service = generateService(failApi);
38+
try {
39+
await service();
40+
} catch (error) {
41+
expect(error.message).toBe('Not Found');
42+
fn();
43+
}
44+
expect(fn).toHaveBeenCalledTimes(1);
45+
});
46+
47+
test('should use object service', async () => {
48+
const service = generateService({
49+
test: 'value',
50+
url: successApi,
51+
});
52+
expect(await service()).toMatchObject(resultData);
53+
});
54+
55+
test('should use function service that will return string', async () => {
56+
const service = generateService(serviceWillReturnString);
57+
expect(await service()).toMatchObject(resultData);
58+
});
59+
60+
test('should use function service that will return object', async () => {
61+
const service = generateService(serviceWillReturnObject);
62+
expect(await service()).toMatchObject(resultData);
63+
});
64+
65+
test('should use function service that will return unknown type', async () => {
66+
const fn = jest.fn();
67+
const service = generateService(serviceWillReturnUnknown as any);
68+
try {
69+
await service();
70+
} catch (error) {
71+
expect(error.message).toBe('Unknown service type');
72+
fn();
73+
}
74+
expect(fn).toHaveBeenCalledTimes(1);
75+
});
76+
77+
test('should throw error when use unknown service', () => {
78+
const fn = jest.fn();
79+
try {
80+
const service = generateService(unknownService as any);
81+
} catch (error) {
82+
expect(error.message).toBe('Unknown service type');
83+
fn();
84+
}
85+
expect(fn).toHaveBeenCalledTimes(1);
86+
});
87+
});

src/core/utils/generateService.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { IService } from './types';
2+
import {
3+
isFunction,
4+
isPlainObject,
5+
isPromise,
6+
isString,
7+
requestProxy,
8+
} from './index';
9+
10+
export default <R, P extends unknown[]>(service: IService<R, P>) => {
11+
let promiseQuery: (() => Promise<R>) | ((...args: P) => Promise<R>);
12+
13+
if (isFunction(service)) {
14+
promiseQuery = (...args: P) => {
15+
const _service = service(...args);
16+
let finallyService: Promise<R>;
17+
// 是否为普通异步请求
18+
if (!isPromise(_service)) {
19+
if (isPlainObject(_service)) {
20+
const { url, ...rest } = _service;
21+
finallyService = requestProxy(url, rest);
22+
} else if (isString(_service)) {
23+
finallyService = requestProxy(_service);
24+
} else {
25+
throw new Error('Unknown service type');
26+
}
27+
} else {
28+
finallyService = _service;
29+
}
30+
31+
return new Promise<R>((resolve, reject) => {
32+
finallyService.then(resolve).catch(reject);
33+
});
34+
};
35+
} else if (isPlainObject(service)) {
36+
const { url, ...rest } = service;
37+
promiseQuery = () => requestProxy(url, rest);
38+
} else if (isString(service)) {
39+
promiseQuery = () => requestProxy(service);
40+
} else {
41+
throw Error('Unknown service type');
42+
}
43+
return promiseQuery;
44+
};

src/core/utils/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Ref } from 'vue';
2+
import { Query } from '../createQuery';
23

34
export type PartialRecord<T> = {
45
[P in keyof T]: Partial<T[P]>;
@@ -13,3 +14,15 @@ export type UnRef<T> = T extends Ref<infer V> ? V : T;
1314
export type UnWrapRefObject<T> = {
1415
[P in keyof T]: UnRef<T[P]>;
1516
};
17+
18+
export type ServiceObject = {
19+
[key: string]: any;
20+
url: string;
21+
};
22+
23+
export type ServiceParams = string | ServiceObject;
24+
25+
export type IService<R, P extends unknown[]> =
26+
| ((...args: P) => ServiceParams)
27+
| ServiceParams
28+
| Query<R, P>;

src/useRequest.ts

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,7 @@
11
import { BaseOptions, FormatOptions, MixinOptions } from './core/config';
2-
import { Query } from './core/createQuery';
32
import useAsyncQuery, { BaseResult } from './core/useAsyncQuery';
4-
import {
5-
isFunction,
6-
isPlainObject,
7-
isPromise,
8-
isString,
9-
requestProxy,
10-
} from './core/utils';
11-
12-
export type ServiceObject = {
13-
[key: string]: any;
14-
url: string;
15-
};
16-
export type ServiceParams = string | ServiceObject;
17-
export type IService<R, P extends unknown[]> =
18-
| ((...args: P) => ServiceParams)
19-
| ServiceParams
20-
| Query<R, P>;
3+
import generateService from './core/utils/generateService';
4+
import { IService } from './core/utils/types';
215

226
function useRequest<R, P extends unknown[] = any>(
237
service: IService<R, P>,
@@ -34,38 +18,7 @@ function useRequest<R, P extends unknown[], FR>(
3418
service: IService<R, P>,
3519
options?: MixinOptions<R, P, FR>,
3620
) {
37-
let promiseQuery: (() => Promise<R>) | ((...args: P) => Promise<R>);
38-
39-
if (isFunction(service)) {
40-
promiseQuery = (...args: P) => {
41-
const _service = service(...args);
42-
let finallyService: Promise<R>;
43-
// 是否为普通异步请求
44-
if (!isPromise(_service)) {
45-
if (isPlainObject(_service)) {
46-
const { url, ...rest } = _service;
47-
finallyService = requestProxy(url, rest);
48-
} else if (isString(_service)) {
49-
finallyService = requestProxy(_service);
50-
} else {
51-
throw new Error('Unknown service type');
52-
}
53-
} else {
54-
finallyService = _service;
55-
}
56-
57-
return new Promise<R>((resolve, reject) => {
58-
finallyService.then(resolve).catch(reject);
59-
});
60-
};
61-
} else if (isPlainObject(service)) {
62-
const { url, ...rest } = service;
63-
promiseQuery = () => requestProxy(url, rest);
64-
} else if (isString(service)) {
65-
promiseQuery = () => requestProxy(service);
66-
} else {
67-
throw Error('Unknown service type');
68-
}
21+
const promiseQuery = generateService(service);
6922

7023
return useAsyncQuery<R, P, FR>(promiseQuery, (options ?? {}) as any);
7124
}

0 commit comments

Comments
 (0)