minigame-std
Version:
Mini Game Standard Development Library.
125 lines (107 loc) • 4.02 kB
text/typescript
import { Err, Ok, type AsyncIOResult, type IOResult } from 'happy-rusty';
import { Future } from 'tiny-future';
import { assertSafeUrl } from '../assert/assertions.ts';
import { miniGameFailureToError } from '../utils/mod.ts';
import { ABORT_ERROR, FetchError, TIMEOUT_ERROR, type FetchTask, type MinaFetchInit } from './fetch_defines.ts';
/**
* 发起一个可中断的 ArrayBuffer 类型响应的网络请求。
* @param url - 请求的 URL 地址。
* @param init - 请求的初始化配置,指定响应类型为 ArrayBuffer 且请求可中断。
* @returns 返回一个 ArrayBuffer 类型的 FetchTask。
*/
export function minaFetch(url: string, init: MinaFetchInit & {
responseType: 'arraybuffer';
}): FetchTask<ArrayBuffer>;
/**
* 发起一个可中断的 JSON 类型响应的网络请求。
* @typeParam T - 预期的 JSON 响应数据类型。
* @param url - 请求的 URL 地址。
* @param init - 请求的初始化配置,指定响应类型为 JSON 且请求可中断。
* @returns 返回一个 JSON 类型的 FetchTask。
*/
export function minaFetch<T>(url: string, init: MinaFetchInit & {
responseType: 'json';
}): FetchTask<T>;
/**
* 发起一个可中断的文本类型响应的网络请求。
* @param url - 请求的 URL 地址。
* @param init - 请求的初始化配置,指定响应类型为文本且请求可中断。
* @returns 返回一个文本类型的 FetchTask。
*/
export function minaFetch(url: string, init?: MinaFetchInit & {
responseType: 'text';
}): FetchTask<string>;
/**
* 发起一个可中断的网络请求,默认返回文本类型响应。
* @param url - 请求的 URL 地址。
* @param init - 请求的初始化配置,指定请求可中断。
* @returns {FetchTask<string>} 返回一个文本类型的 FetchTask。
*/
export function minaFetch(url: string, init: MinaFetchInit): FetchTask<string>;
/**
* 发起一个网络请求,根据初始化配置返回对应类型的 FetchTask。
* @typeParam T - 预期的响应数据类型。
* @param url - 请求的 URL 地址。
* @param init - 请求的初始化配置。
* @returns 根据配置返回 FetchTask。
*/
export function minaFetch<T>(url: string, init?: MinaFetchInit): FetchTask<T> {
assertSafeUrl(url);
const {
responseType,
onChunk,
...rest
} = init ?? {};
let aborted = false;
const future = new Future<IOResult<T>>();
const options: WechatMinigame.RequestOption = {
...rest,
url,
success(res) {
const { statusCode } = res;
if (statusCode >= 200 && statusCode < 300) {
future.resolve(Ok(res.data as T));
} else {
future.resolve(Err(new FetchError(res.errMsg, statusCode)));
}
},
fail(err) {
const error = miniGameFailureToError(err);
const { errMsg } = err;
if (errMsg.includes('abort')) {
error.name = ABORT_ERROR;
} else if (errMsg.includes('timeout')) {
error.name = TIMEOUT_ERROR;
}
future.resolve(Err(error));
},
};
if (responseType === 'arraybuffer') {
options.responseType = responseType;
} else if (responseType === 'json') {
options.dataType = responseType;
} else {
// default responseType is text
options.responseType = responseType;
// responseType设置为text还不够,否则返回类型还是json
options.dataType = '其他';
}
const task = wx.request(options);
if (typeof onChunk === 'function') {
task.onChunkReceived(res => {
onChunk(new Uint8Array(res.data));
});
}
return {
abort(): void {
aborted = true;
task.abort();
},
get aborted(): boolean {
return aborted;
},
get response(): AsyncIOResult<T> {
return future.promise;
},
};
}