@ithinkdt/core
Version:
iThinkDT Core
95 lines (91 loc) • 3.14 kB
JavaScript
import { inject, ref, shallowRef } from 'vue'
import { request, HttpError } from '@ithinkdt/common'
import { $FETCH } from './plugin'
export function useFetch(api, options = {}) {
let fn,
options2 = {}
if (!api) {
api = 'get: '
}
if (typeof api === 'function') {
fn = api
} else {
const $fetch = options?.$fetch ?? inject($FETCH, request)
let _api
if (typeof api === 'string') {
const index = api.indexOf(':')
const [method, reqType] = api.slice(0, Math.max(0, index)).split('|')
_api = {
url: api.slice(Math.max(0, index + 1)),
method,
reqType,
}
} else {
_api = api
}
options.method = _api.method ?? options?.method
const {
url,
method = options.method ?? 'get',
before,
after,
shallow,
resetOnExecute,
initResult,
...requestOptions
} = Object.assign({}, _api, options)
options2 = { before, after, shallow, resetOnExecute, initResult }
const isGet = method.toLowerCase() === 'get'
fn = (params, options3 = {}) => {
let req
if (params instanceof Request) {
req = params
} else {
req = {
...requestOptions,
...options3,
}
if (isGet) {
req.params = params
} else {
req.body = params
}
}
return $fetch(method, url, req)
}
}
const loading = ref(false)
const result = (options.shallow === false ? ref : shallowRef)(options?.initResult)
const state = ref('inited')
const _before = [options.before, options2.before]
const _after = [options2.after, options.after]
const _fn = (params, options3) => {
if (options2.resetOnExecute || options.resetOnExecute) result.value = options?.initResult
loading.value = true
state.value = 'loading'
// eslint-disable-next-line unicorn/no-array-reduce
params = _before.reduce((params, before) => (before ? before(params) ?? params : params), params)
const req = Promise.resolve(fn(params, options3))
req.then(
(res) => {
state.value = 'success'
// eslint-disable-next-line unicorn/no-array-reduce
result.value = _after.reduce((res, after) => (after ? after(res) ?? res : res), res)
},
(error) => {
state.value = error?.name === 'AbortError' ? 'abort' : 'error'
if (state.value !== 'abort') {
console[error instanceof HttpError ? 'debugger' : 'error'](`[use-fetch]: `, error)
}
},
).finally(() => {
loading.value = false
})
return req
}
_fn.loading = loading
_fn.state = state
_fn.result = result
_fn.exec = _fn
return _fn
}