Skip to content

Commit ad4fd10

Browse files
committed
feat: 🎉 optimize some logic of util
1 parent 0bb4ef1 commit ad4fd10

File tree

6 files changed

+35
-59
lines changed

6 files changed

+35
-59
lines changed

src/__tests__/object.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { hasFiles, hasOwnProperty, isFile } from '../util'
1+
import { hasFiles, isFile } from '../util'
22

33
describe('Object Test', () => {
44
// const { window, File } = global
@@ -10,9 +10,6 @@ describe('Object Test', () => {
1010
const file = new File(['hello world!'], 'myfile')
1111
expect(isFile(file)).toBeTruthy()
1212
})
13-
it('should check has own property', function () {
14-
expect(hasOwnProperty({ dev: null }, '')).toBeFalsy()
15-
})
1613
it('check if window is undefined', () => {
1714
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
1815
// @ts-ignore

src/core/BaseService.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { AxiosError, AxiosInstance, Method, AxiosRequestConfig, AxiosResponse } from 'axios'
22
import type { IParseOptions } from 'qs'
3-
import { isObject, isArray } from 'lodash'
3+
import { isObject } from 'lodash'
44
import qs from 'qs'
55
import Validator from './Validator'
66
import { hasFiles, objectToFormData } from '../util'
@@ -86,11 +86,12 @@ export default class BaseService {
8686
$submit<T = any, F = any>(method: Method, param?: string | number, form?: F, config?: AxiosRequestConfig) {
8787
this.beforeSubmit()
8888
return new Promise<AxiosResponse<T>>((resolve, reject) => {
89-
const data = hasFiles(form) ? objectToFormData(form) : form
90-
const endpoint = param ? `/${this.endpoint}/${param}` : `/${this.endpoint}`
91-
const url = this.__getParameterString(endpoint.replace(/\/\//g, '/'))
92-
config = Object.assign({}, config, { url, data, method })
93-
this.$http(config)
89+
const formData = hasFiles(form) ? objectToFormData(form) : form
90+
const endpointPath = param ? `/${this.endpoint}/${param}` : `/${this.endpoint}`
91+
const endpoint = endpointPath.replace(/\/\//g, '/')
92+
const url = this.__getParameterString(endpoint)
93+
const axiosConfig = { url, data: formData, method, ...config }
94+
this.$http(axiosConfig)
9495
.then((response) => {
9596
this.onSuccess()
9697
resolve(response)
@@ -101,9 +102,9 @@ export default class BaseService {
101102
const { response } = error
102103
if (response && response.status === UNPROCESSABLE_ENTITY) {
103104
const { data } = response
104-
const errors: Record<string, any> = {}
105-
Object.assign(errors, data[this.$errorProperty])
106-
this.onFail(errors)
105+
const validationErrors: Record<string, any> = {}
106+
Object.assign(validationErrors, data[this.$errorProperty])
107+
this.onFail(validationErrors)
107108
}
108109
reject(error)
109110
})
@@ -148,7 +149,7 @@ export default class BaseService {
148149
removeParameters(parameters: string[] = []) {
149150
if (!parameters || !parameters.length) {
150151
this.parameters = {}
151-
} else if (isArray(parameters)) {
152+
} else if (Array.isArray(parameters)) {
152153
for (const parameter of parameters) delete this.parameters[parameter]
153154
}
154155
return this

src/core/Validator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class Validator {
117117
}
118118

119119
fields(field: string | string[]): string[] {
120-
const fields = []
120+
const fields: string[] = []
121121
if (Array.isArray(field)) {
122122
for (const f of field) {
123123
fields.push(toCamelCase(f), toSnakeCase(f))

src/util/formData.ts

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import { hasOwnProperty, isArray, isFile } from './objects'
1+
import { isFile } from './objects'
22

3-
const getKey = (parent: any, property: any) => (parent ? parent + '[' + property + ']' : property)
43
export function objectToFormData(obj: any, formData = new FormData(), parent = ''): FormData {
5-
if (obj === null || obj === 'undefined' || obj.length === 0) {
4+
if (obj == null || (Array.isArray(obj) && obj.length === 0)) {
65
formData.append(parent, obj)
76
} else {
8-
for (const property in obj) {
9-
if (hasOwnProperty(obj, property)) {
10-
appendToFormData(formData, getKey(parent, property), obj[property])
11-
}
7+
const propertyMap = new Map(Object.entries(obj))
8+
for (const [property, value] of propertyMap) {
9+
const key = parent ? `${parent}[${property}]` : property
10+
appendToFormData(formData, key, value)
1211
}
1312
}
1413
return formData
@@ -19,37 +18,34 @@ function appendToFormData(formData: FormData, key: string, value: any) {
1918
if (typeof value === 'boolean') return formData.append(key, value ? '1' : '0')
2019
if (value === null) return formData.append(key, '')
2120
if (typeof value !== 'object') return formData.append(key, value)
22-
if (isArray(value) && hasFilesDeep(value)) {
21+
if (Array.isArray(value) && hasFilesDeep(value)) {
2322
for (let i = 0; i < value.length; i++) {
2423
formData.append(key + '[' + i + ']', value[i], value[i].name)
2524
}
2625
return formData
2726
}
28-
objectToFormData(value, formData, key)
27+
if (typeof value === 'object') return objectToFormData(value, formData, key)
28+
throw new Error(`Unexpected value type: ${typeof value}`)
2929
}
3030
export function hasFilesDeep(obj: any): boolean {
3131
if (obj === null) return false
3232
if (typeof obj === 'object') {
33-
for (const key in obj) {
34-
if (isFile(obj[key])) return true
33+
const values = Object.values(obj)
34+
for (let i = 0; i < values.length; i++) {
35+
if (isFile(values[i])) return true
3536
}
3637
}
37-
if (isArray(obj)) {
38-
let f = ''
39-
for (const key in obj) {
40-
if (hasOwnProperty(obj, key)) {
41-
f = key
42-
break
43-
}
44-
}
45-
return hasFilesDeep(obj[f])
38+
if (Array.isArray(obj)) {
39+
const firstNonNullElement = obj.find((el) => el !== null)
40+
return firstNonNullElement ? hasFilesDeep(firstNonNullElement) : false
4641
}
4742
return isFile(obj)
4843
}
4944
export function hasFiles(form: any) {
5045
for (const prop in form) {
51-
const hasProp = hasOwnProperty(form, prop) || typeof window !== 'undefined'
52-
if (hasProp && hasFilesDeep(form[prop])) return true
46+
if (Object.prototype.hasOwnProperty.call(form, prop) && hasFilesDeep(form[prop])) {
47+
return true
48+
}
5349
}
5450
return false
5551
}

src/util/objects.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,6 @@
1-
export function isArray(object: any): boolean {
2-
return Object.prototype.toString.call(object) === '[object Array]'
3-
}
4-
5-
export function hasOwnProperty(obj: any, key: any) {
6-
if (!obj || !key) return false
7-
return Object.prototype.hasOwnProperty.call(obj, key)
8-
}
9-
101
export function isFile(object: any): boolean {
11-
if (typeof window === 'undefined' || typeof File !== 'function' || typeof FileList !== 'function') {
12-
return false
13-
}
142
return object instanceof File || object instanceof FileList
153
}
16-
17-
export function is(errors: any, error: any): boolean {
18-
return isArray(error) ? error.some((w: string) => is(errors, w)) : errors.includes(error)
4+
export function is(errors: string[], errorsToCheck: string[] | string): boolean {
5+
return Array.isArray(errorsToCheck) ? errorsToCheck.some((w) => is(errors, w)) : errors.includes(errorsToCheck)
196
}

src/util/string.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,2 @@
1-
export const toCamelCase = (e: string) => {
2-
return e.replace(/_([a-z])/g, (g) => g[1].toUpperCase())
3-
}
4-
export const toSnakeCase = (e: string) => {
5-
if (!e.match(/([A-Z])/g)) return e
6-
return e.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)
7-
}
1+
export const toCamelCase = (e: string) => e.replace(/_([a-z])/g, (g) => g[1].toUpperCase())
2+
export const toSnakeCase = (e: string) => (e.match(/([A-Z])/g) ? e.replace(/[A-Z]/g, (l) => `_${l.toLowerCase()}`) : e)

0 commit comments

Comments
 (0)