Koa 中实现 chunked 数据传输
| 有關于 Transfer-Encoding:chunked 類型的響應,參見之前的文章HTTP 響應的分塊傳輸。這里看 Koa 中如何實現。 Koa 中請求返回的處理雖然官方文檔有描述說明不建議直接調用 response.write: Bypassing Koa's response handling is not supported. Avoid using the following node properties:
但要實現分片向客戶端發送數據,必然還是得調用 Node.js Http 模塊的 response.write(chunk[, encoding][, callback]) 方法,而這里的 response 就是 ctx.res 或 ctx.response。 所以為什么 Koa 要說不建議直接調用上述方法操作請求的返回呢,我們來看看 Koa 內部對 response 都會做些什么默認的處理。 application.js handleRequest(ctx, fnMiddleware) {const res = ctx.res;res.statusCode = 404;const onerror = err => ctx.onerror(err);const handleResponse = () => respond(ctx);onFinished(res, onerror);return fnMiddleware(ctx).then(handleResponse).catch(onerror);}在應用完各種中間件后(fnMiddleware(ctx))通過 handleResponse 對請求進行一些操作,最終是在 respond 函數里。 respond 方法 function respond(ctx) {// allow bypassing koaif (false === ctx.respond) return;if (!ctx.writable) return;const res = ctx.res;let body = ctx.body;const code = ctx.status;// ignore bodyif (statuses.empty[code]) {// strip headersctx.body = null;return res.end();}if ('HEAD' == ctx.method) {if (!res.headersSent && isJSON(body)) {ctx.length = Buffer.byteLength(JSON.stringify(body));}return res.end();}// status bodyif (null == body) {if (ctx.req.httpVersionMajor >= 2) {body = String(code);} else {body = ctx.message || String(code);}if (!res.headersSent) {ctx.type = 'text';ctx.length = Buffer.byteLength(body);}return res.end(body);}// responsesif (Buffer.isBuffer(body)) return res.end(body);if ('string' == typeof body) return res.end(body);if (body instanceof Stream) return body.pipe(res);// body: jsonbody = JSON.stringify(body);if (!res.headersSent) {ctx.length = Buffer.byteLength(body);}res.end(body); }respond 方法里會根據外部是否有設置過 ctx.body,以及不同的 header 來設置 ctx.body,最終會調用 response.end 來結束掉本次請求。 注意到如果設置了 ctx.respond = false,這個方法就直接 return 了,這是一種跳過這里處理的方式。但其實如果我們在中間件中手動調用了 ctx.res.end() 后,相當于已經提前結束掉請求了,同樣也不會走 Koa 這里的處理。 所以直接在中間件中調用 ctx.res.write() 及 ctx.res.end() 就可以實現 chunked 類型的響應,倒無須對 Koa 做額外設置。 Koa 實現 chunked 數據傳輸根據上面的分析,及之前一篇關于HTTP 響應的分塊傳輸的文章,我們得出以下 Koa 中的實現邏輯: const Koa = require("koa"); const app = new Koa(); const PORT = 3000; app.use((ctx, _next) => {const res = ctx.res;ctx.status = 200;res.setHeader("Content-Type", "text/html");res.write(`start<br>`);return new Promise(resolve => {let i = 0,total = 5;while (i <= total) {(function(i) {setTimeout(() => {if (i === total) {resolve();res.end();} else {res.write(`${i}<br>`);}}, i * 1000);})(i);i++;}}); });app.listen(PORT); console.info(`server started at http://localhost:${PORT}`);運行效果: Koa 中實現 chunked 響應的運行效果 如你所見,Koa 中的這個實現會在調用 ctx.res.end() 后將本來應該在頁面內容中處于最頂部的內容,移動到最底部。不解。 或者通過 curl 在命令行中查看效果: $ curl -N http://localhost:3000命令行中接收 chunked 數據的效果 示例代碼可在 wayou/koa-chunked-response 找到。 相關資源
|
轉載于:https://www.cnblogs.com/Wayou/p/koa_transfer_encoding_chunked.html
總結
以上是生活随笔為你收集整理的Koa 中实现 chunked 数据传输的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 孕妇梦到韭菜是什么意思
- 下一篇: 做梦梦到钱和屎是什么意思