Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一个基于 React-Native 0.75 Expo 51 的成功案例。 #26

Open
ContinueOneSecond opened this issue Oct 20, 2024 · 0 comments
Open

Comments

@ContinueOneSecond
Copy link

ContinueOneSecond commented Oct 20, 2024

首先感谢该项目的所有开源贡献者
环境:

  • React-Native 0.75
  • Expo 51

先说为什么还是选择了fetch:rn-sse、event-source 同样是非常优秀的开源项目,但是不太满足我的HttpRequest需求,以及EventSource会使我的Markdown混乱,我无法解决。

在我尝试了 axion、websocket、rn-sse、event-source 以及数个小时的调试和大量的翻译工作后,终于在这个项目中取得到了结果。

在各种论坛上徘徊后,我找到了该项目,以下是我最低限度的实践:

  1. 我安装了文档中所有的依赖,并且在项目根目录创建了 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";
  1. 请求示例
 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);
        }
    }
  1. 解析示例
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?.();
    }
}

希望可以帮助到有需要的人。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant