base/src/http.js

62 lines
2.7 KiB
JavaScript
Raw Normal View History

// src/http.js
(function(global) {
const { Component, NewState } = global;
const HTTP = {
get: ({ url, ...opt }) => HTTP.request({ url, method: 'GET', ...opt }),
post: ({ url, data, ...opt }) => HTTP.request({ url, method: 'POST', data, ...opt }),
put: ({ url, data, ...opt }) => HTTP.request({ url, method: 'PUT', data, ...opt }),
delete: ({ url, ...opt }) => HTTP.request({ url, method: 'DELETE', ...opt }),
head: ({ url, ...opt }) => HTTP.request({ url, method: 'HEAD', ...opt }),
request: async ({ url, method = 'POST', data = undefined, headers = {}, responseType, timeout = 10000 }) => {
method = method.toUpperCase()
const opt = { method, headers: { 'Content-Type': 'application/json', ...headers } }
if (data !== undefined) opt.body = JSON.stringify(data)
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeout)
opt.signal = controller.signal
try {
const response = await fetch(url, opt)
clearTimeout(timer)
const result = responseType === 'blob' ? await response.blob() : (responseType === 'text' ? await response.text() : await response.json())
return { ok: response.ok, status: response.status, result }
} catch (err) {
clearTimeout(timer)
return { ok: false, status: 0, error: err.message }
}
}
};
Component.register('API', container => {
if (!container.state.request) container.state.request = { url: '', method: 'GET', data: {}, noui: false }
if (!container.state.response) container.state.response = { ok: false, status: 0, result: null, loading: false }
container.do = async (req) => {
const opt = { ...container.state.request, ...req }
container.state.response.loading = true
const resp = await HTTP.request(opt)
Object.assign(container.state.response, resp, { loading: false })
if (!resp.ok) {
if (!opt.noui && global.UI?.toast) global.UI.toast(resp.error || 'Request failed', { type: 'danger' })
}
container.dispatchEvent(new CustomEvent('success', { bubbles: false, detail: resp.result }))
return resp
}
let _autoTimer = null
container.state.request.__watch(null, () => {
if (!container.hasAttribute('auto') || !container.state.request.url) return
if (_autoTimer) return
_autoTimer = Promise.resolve().then(() => {
container.do()
_autoTimer = null
})
})
});
global.HTTP = HTTP;
})(globalThis);