http 返回进度请求

339 阅读1分钟

需求:客户端在请求时,服务端在收到请求后拿数据可能非常慢,只有拿到数据后才能返回请求。如果我们希望服务端一边拿数据一边向客户端传输,而不是等服务端拿完数据后才向返回给客户端。我们当然可以用socket.io。但还有一种方案就是长连接

应用场景
  • 一边查询数据,一边向客户端返回
  • 删除大量数据时返回进度
  • 读取或解析文件时返回进度
问题,希望有人能够解答
  1. 我本人的服务端使用的nodejs 中的express。在使用res.write() 写入数据时,有没有那没法使传输的数据使用gzip压缩。
  2. 我本人在客户端使用的时fetch测试。我不知道如果用axios如何拿到 response.body 流
案例,实现一个服务端读取文件返回进度的请求
  1. 服务端
const express = require('express');
const fs = require('fs');

const app = express();

const port = 3000;

app.use(express.json());

app.post('read-progress'(req,res)=>{
	let path = './中华道藏全集.txt';
	let info = fs.statSync(path)
    let stream = fs.createReadStream(path);

	let size = 0

	stream.on('data', function (buffer) {
        size += buffer.byteLength
        let progress= (size/info.size).toFixed(2);
	    res.write((progress).toString() + ',')
	})

	 stream.on('end', function () {
        res.end();
    })
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})
  1. 客户端
async function main(){
	let response = await fetch('/read-progress');

	const reader = response.body.getReader();
    const decode = new TextDecoder();

	let progress=document.createElement('progress');
    document.body.appendChild(progress);

	const processData = (result) =>{
		if (result.done) {
            return
        }

		const value = result.value;
        let text = decode.decode(value.buffer);
        let arr = text.split(',')

		let str = arr[arr.length - 1] || arr[arr.length - 2]
        progress.value = parseFloat(str)/100;
		
		return reader.read().then(processData);
	}

	reader.read().then(processData);
}

window.onload = main;