During this period of time working on the AI-QA platform, I encountered a business requirement for GPT like post streaming response: by sending post issues to the backend, the backend adopts streaming response, which means returning data in segments and then rendering the style. I encountered a problem here, Axios cannot respond to post streaming.
On the contrary, native fetch can achieve post streaming processing.
1//核心代码
2async function run() {
3 aborter.abort(); // cancel previous request
4 outputEl.innerText = "";
5 aborter = new AbortController();
6 const prompt = new FormData(formEl).get("prompt");
7 try {
8 const response = await fetch("http://192.168.223.26:5000/chain", {
9 signal: aborter.signal,
10 method: "POST",
11 headers: { "Content-Type": "application/json" },
12 body: JSON.stringify({
13 prompt,
14 }),
15 });
16 const reader = response.body.getReader();
17 const decoder = new TextDecoder();
18 while (true) {
19 const { done, value } = await reader.read();
20 if (done) {
21 break;
22 }
23 const decoded = decoder.decode(value, { stream: true });
24 console.log(decoded);
25 outputEl.innerText += decoded;
26 }
27 } catch (err) {
28 console.error(err);
29 }
30}
31
So I went to check the relevant information and found thatAxios
It seems that some places are really inferiorFetch
Axios
It is based onPromise
The network request library uses the built-in HTTP module of Node.js on the node side and XMLHttpRequests on the browser side. Its functions include but are not limited to intercepting requests and responses, automatically converting JSON data, and canceling requests.
More content can be viewed directlyOfficial website.
What is the main topic hereXHR(XMLHttpRequests):
XHR is an early browser built-in object that, although named XML, can not only manipulate data in XML format, but also other data such as images, documents, and so on. But with the emergence of the updated fetch, XHR gradually disappeared, and the only reason it remained is probably to be compatible with old browsers, adapt to old scripts, and track upload progress (which fetch cannot do).
XMLHttpRequest has two execution modes: synchronous and asynchronous
Let's first take a look at the most commonly used asynchronous:
1. CreateXMLHttpRequest
1let xhr = new XMLHttpRequest();
2
2. Initialize it
1xhr.open(method, URL, [async, user, password]);
2
3. Send a request
1xhr.send([body]);
2
4. Monitor XHR events to obtain responses
1xhr.onload = function () {
2 alert(`Loaded: ${xhr.status} ${xhr.response}`);
3};
4
5xhr.onerror = function () {
6 // 仅在根本无法发出请求时触发
7 alert(`Network Error`);
8};
9
10xhr.onprogress = function (event) {
11 // 定期触发
12 // event.loaded —— 已经下载了多少字节
13 // event.lengthComputable = true,当服务器发送了 Content-Length header 时
14 // event.total —— 总字节数(如果 lengthComputable 为 true)
15 alert(`Received ${event.loaded} of ${event.total}`);
16};
17
Typical code for XHR Get request (probably not needed now):
1let xhr = new XMLHttpRequest();
2
3xhr.open("GET", "/my/url");
4
5xhr.send();
6
7xhr.onload = function () {
8 if (xhr.status != 200) {
9 // HTTP error?
10 // 处理 error
11 alert("Error: " + xhr.status);
12 return;
13 }
14
15 // 获取来自 xhr.response 的响应
16};
17
18xhr.onprogress = function (event) {
19 // 报告进度
20 alert(`Loaded ${event.loaded} of ${event.total}`);
21};
22
23xhr.onerror = function () {
24 // 处理非 HTTP error(例如网络中断)
25};
26
As mentioned earlier, XML can track upload progress in a way that Fetch cannot - xhr.upload
It generates events, similar to XHR, but XHR. upload only triggers them when uploading:
Example:
1xhr.upload.onprogress = function (event) {
2 alert(`Uploaded ${event.loaded} of ${event.total} bytes`);
3};
4
5xhr.upload.onload = function () {
6 alert(`Upload finished successfully.`);
7};
8
9xhr.upload.onerror = function () {
10 alert(`Error during the upload: ${xhr.status}`);
11};
12
Fetch is a modern and universal JS network request method
Its advantages lie in:
But it still has its drawbacks:
Next, let's take a look at the relevant process of Fetch
Basic grammar:
1let promise = fetch(url, [options]);
2
The browser immediately initiates the request and returns a promise that the calling code should be used to obtain the result. Obtaining a response usually requires two stages.
In the first stage, when the server sends a response header, the promise returned by fetch uses the built-in Response class object to parse the response header.
At this stage, we can confirm whether the request is successful by checking the status of the response header. If the fetch cannot be successfully established, that is, if there are network problems or other network issues, the promise will be rejected.
Therefore, all server returns such as 404 or 500 will not cause Promise to return reject, making it difficult to track errors.
In the second stage, in order to obtain the response body, we need to call another method.
Response provides multiple promise based methods to access the body in different formats:
Response. text() - Read the response and return it in text format,
Response. json () - parses the response into JSON format,
Response. formData() - returns a response in the form of a FormData object (explained in the next chapter),
Response. blob() - returns a response in the form of a Blob (binary data with a type),
Response. arrayBuffer() - returns the response in the form of an ArrayBuffer (low-level binary data),
In addition, responsive.body is a ReadableStream object that allows you to read the body block by block. The GPTpost response stream is based on this for streaming responses:
1const response = await fetch("http://192.168.223.26:5000/chain", {
2 signal: aborter.signal,
3 method: "POST",
4 headers: { "Content-Type": "application/json" },
5 body: JSON.stringify({
6 prompt,
7 }),
8});
9const reader = response.body.getReader();
10
We can only choose one method to read the body. If we have already used the response. text() method to obtain the response, then using response. json () will not take effect because the body content has already been processed.
XML: Extensible Markup Language (XML) is a markup language. XML is simplified and modified from Standard Generalized Markup Language (SGML).
AJAX (Asynchronous JavaScript And XML) is a programming practice that uses XMLHttpRequest technology to build more complex and dynamic web pages. The implementation methods include the ancient XHR and the new Fetch.
HTTP module: The HTTP module refers to the HTTP module in the node, including: