Open
Description
首先感谢该项目的所有开源贡献者
环境:
- React-Native 0.75
- Expo 51
先说为什么还是选择了fetch:rn-sse、event-source 同样是非常优秀的开源项目,但是不太满足我的HttpRequest需求,以及EventSource会使我的Markdown混乱,我无法解决。
在我尝试了 axion、websocket、rn-sse、event-source 以及数个小时的调试和大量的翻译工作后,终于在这个项目中取得到了结果。
在各种论坛上徘徊后,我找到了该项目,以下是我最低限度的实践:
- 我安装了文档中所有的依赖,并且在项目根目录创建了 index.js
这里有几个地方需要说明:
import { polyfill as polyfillReadableStream } from 'react-native-polyfill-globals/src/readable-stream';
web-streams-polyfill/ponyfill/es6
加载时会报错,于是我使用const { ReadableStream } = require('web-streams-polyfill/dist/ponyfill.es5.js');
代替
polyfillEncoding();
使用 react-native-polyfill-globals
提供的
polyfillFetch();
使用 react-native-polyfill-globals
提供的
参考:
https://stackoverflow.com/questions/56207968/stream-api-with-fetch-in-a-react-native-app/77089139#77089139
另外我遇到了一些其他上面的异常,但是介于当前是最小可行性的示例,不进行赘述。
index.js
// import 'react-native-polyfill-globals/auto';
// import { polyfill as polyfillBase64 } from 'react-native-polyfill-globals/src/base64';
// import { polyfill as polyfillReadableStream } from 'react-native-polyfill-globals/src/readable-stream';
// import { polyfill as polyfillURL } from 'react-native-polyfill-globals/src/url';
// import { polyfill as polyfillCrypto } from 'react-native-polyfill-globals/src/crypto';
import { polyfillGlobal } from 'react-native/Libraries/Utilities/PolyfillFunctions';
import { polyfill as polyfillEncoding } from 'react-native-polyfill-globals/src/encoding';
import { polyfill as polyfillFetch } from 'react-native-polyfill-globals/src/fetch';
const { ReadableStream } = require('web-streams-polyfill/dist/ponyfill.es5.js');
// 调用 polyfill 函数
polyfillFetch();
// polyfillReadableStream();
// polyfillBase64();
// polyfillURL();
// polyfillCrypto();
// polyfillFetch();
polyfillEncoding();
polyfillGlobal("ReadableStream", () => ReadableStream);
// polyfillGlobal(
// "fetch",
// () =>
// (...args: any[]) =>
// fetch(args[0], { ...args[1], reactNative: { textStreaming: true } }),
// );
// polyfillGlobal("Headers", () => Headers);
// polyfillGlobal("Request", () => Request);
// polyfillGlobal("Response", () => Response);
// polyfillGlobal('TextEncoder', () => TextEncoder);
// polyfillGlobal('TextDecoder', () => TextDecoder);
import "expo-router/entry";
- 请求示例
static async post_stream(url: string, params?: Record<string, any>): Promise<ReadableStreamDefaultReader<Uint8Array>> {
const token = await this.getToken();
try {
const response = await fetch(url, {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token.token}` : '',
'Accept': 'text/event-stream'
},
//@ts-ignore
reactNative: { textStreaming: true },
body: JSON.stringify(params)
});
//检查普通异常
checkStream(response);
if (response.body === null) {
throw new BizError("500", "网络错误,请稍后重试");
}
return response.body.getReader();
} catch (error) {
throw checkError(error);
}
}
- 解析示例
export const useStreamReader = async ({reader, onData,onOpen, onError, onComplete}: StreamReaderProps) => {
let isReading = false;
const decoder = new TextDecoder('utf-8');
try {
isReading = true;
onOpen?.();
while (isReading) {
const {done, value} = await reader.read();
console.log("org",value);
if (done) {
onComplete?.();
break;
}
const decodedData = decoder.decode(value);
console.log("before",decodedData)
let strings = decodedData.split("data:");
let res = "";
strings.forEach((str) => {
if(str === ''){
return;
}
if (str.endsWith("\n\n")) {
str = str.slice(0, -2);
}
const data = str.replace("data:","");
res += data;
})
onData(res);
}
} catch (error) {
console.error(error);
isReading = false;
onError?.(error);
} finally {
isReading = false;
onComplete?.();
}
}
希望可以帮助到有需要的人。
Metadata
Metadata
Assignees
Labels
No labels