这与Java的跨平台属性有着显著的不同。JVM提供了一个完全抽象的层次,开发者理论上不必关心同一段代码在不同平台上的表现问题。JavaScript则将这一责任移交给开发人员,各大宿主平台仿佛只是读代码的机器,读到一半很任性地抛给你一个xxx is not implemented都是意料之中的(没错,说的就是你)。开发者需要自己进行兼容与缝合。
/** * Gets the response data from the given `url`, with a specified `referer` if * provided. * * If param `post` is provided, a `POST` request with the given post form will * be sent. Otherwise, a `GET` request will be sent. * * The `timeout` is `60000` by default, in milliseconds. */ exportconst uFetch = async ( url: string, referer?: string, post?: object | string, timeout = 60000, ): Promise<string> => { // Prepare request headers const defaultHeaders = { // Setup content-type and user-agent "Content-Type": CONTENT_TYPE_FORM, "User-Agent": USER_AGENT, };
const headersWithCookies = global.FileReader === undefined ? { ...defaultHeaders, // Cookie should be manually set in Node.js Cookie: Object.keys(cookies).map((key) =>`${key}=${cookies[key]}`).join(";"), } : defaultHeaders;
// Add referer to header if specified const headers = referer === undefined ? headersWithCookies : {...headersWithCookies, Referer: referer};
// Detect charset based on content-type const contentType = response.headers.get("Content-Type"); let base64 = false; let charset = "UTF-8"; if (contentType) { if (contentType.includes("application/octet-stream")) { base64 = true; } else { /charset=(.*?);/.test(contentType + ";"); charset = RegExp.$1; } }
if (global.FileReader) { // For browser and react-native const blob = await response.blob(); returnawaitnewPromise<string>(((resolve, reject) => { // Use FileReader to read blob data const reader = newFileReader(); reader.onloadend = () => { if (typeof reader.result === "string") { if (base64) { // Simply return the string data with the MIME header removed resolve(reader.result.substr("data:application/octet-stream;base64,".length)); } else { // The value stored in `reader.result` has already been parsed with the correct encoding resolve(reader.result); } } else { // This should not happen reject(newError("Blob parsing error.")); } }; // Read and transform if (base64) { reader.readAsDataURL(blob); } else { reader.readAsText(blob, charset); } })); } else { // For node.js const arrayBuffer = await response.arrayBuffer(); // Use iconv-lite to transform arrayBuffer into string return iconv.decode(Buffer.from(arrayBuffer), charset); } } finally { // We have to clear the timeout clearTimeout(timeoutEvent); } };