@canlooks/ajax
Version:
A private tool
172 lines (171 loc) • 5.89 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.core = core;
const error_1 = require("./error");
const util_1 = require("./util");
async function core(config) {
let { url, params, onUploadProgress, onDownloadProgress, timeout = !onUploadProgress && !onDownloadProgress ? 60_000 : void 0, responseType = onDownloadProgress ? void 0 : 'json', ...init } = config;
/**
* ------------------------------------------------------------------
* URL
*/
if (!url) {
throw new error_1.AjaxError(`"url" is required`, { config });
}
if (params) {
if (!(params instanceof URLSearchParams)) {
params = new URLSearchParams(params);
}
if (params.size) {
if (url instanceof URL) {
for (const [name, value] of params) {
url.searchParams.set(name, value);
}
}
else {
url += `${url.includes('?') ? '&' : '?'}${params}`;
}
}
}
/**
* ------------------------------------------------------------------
* 超时与中断
*/
let abortController;
let timeoutId;
if (timeout) {
abortController ||= new AbortController();
timeoutId = setTimeout(() => {
abortController.abort(new error_1.TimeoutError(void 0, { config }));
}, timeout);
}
if (config.signal) {
abortController ||= new AbortController();
config.signal.addEventListener('abort', () => {
abortController.abort(new error_1.AbortError(void 0, { config }));
});
}
/**
* ------------------------------------------------------------------
* 请求
*/
let response;
const { body } = init;
try {
response = await fetch(url, {
...init,
body: (0, util_1.bodyTransform)(body),
signal: abortController?.signal,
});
}
catch (e) {
console.error(e);
throw e instanceof error_1.AjaxError ? e : new error_1.NetworkError(void 0, { config });
}
if (!response.ok) {
throw new error_1.NetworkError(`request failed with status ${response.status}`, { config, response });
}
let result;
/**
* ------------------------------------------------------------------
* 进度
*/
try {
if (onUploadProgress) {
const blob = body instanceof ReadableStream
? await new Response(body).blob()
: (0, util_1.findBodyFiles)(body);
if (blob) {
const reader = blob.stream().getReader();
let loaded = 0;
const total = blob.size;
const read = async () => {
const { done, value } = await reader.read();
if (done) {
return;
}
onUploadProgress({
loaded: loaded += value.byteLength,
total,
chunk: value
});
await read();
};
await read();
}
}
if (onDownloadProgress) {
const contentLength = response.headers.get('content-length');
if (contentLength && response.body) {
let data = new Uint8Array();
const writableStream = new WritableStream({
write(chunk) {
const totalLength = data.byteLength + chunk.byteLength;
const newData = new Uint8Array(totalLength);
newData.set(data);
newData.set(chunk, data.byteLength);
data = newData;
onDownloadProgress({
loaded: data.byteLength,
total: +contentLength,
chunk
});
},
close() {
result = data;
}
});
await response.body.pipeTo(writableStream);
}
}
}
catch (e) {
console.error(e);
throw e instanceof error_1.AjaxError ? e : new error_1.AjaxError(void 0, { config, response });
}
/**
* ------------------------------------------------------------------
* 响应
*/
clearTimeout(timeoutId);
if (onDownloadProgress) {
switch (responseType) {
case 'arrayBuffer':
result = result.buffer;
break;
case 'blob':
const blob = new Blob([result]);
result = blob;
break;
case void 0:
break;
default:
throw new error_1.AjaxError(`"${responseType}" is not supported when using "onDownloadProgress"`, { config, response });
}
}
else {
try {
switch (responseType) {
case 'json':
result = await response.json();
break;
case 'text':
result = await response.text();
break;
case 'blob':
result = await response.blob();
break;
case 'arrayBuffer':
result = await response.arrayBuffer();
break;
case 'formData':
result = await response.formData();
}
}
catch (e) {
console.error(e);
throw e instanceof error_1.AjaxError ? e : new error_1.AjaxError(void 0, { config, response });
}
}
return { result, response, config };
}