Koa 中实现 chunked 数据传输
| 有關(guān)于 Transfer-Encoding:chunked 類型的響應(yīng),參見之前的文章HTTP 響應(yīng)的分塊傳輸。這里看 Koa 中如何實(shí)現(xiàn)。 Koa 中請(qǐng)求返回的處理雖然官方文檔有描述說明不建議直接調(diào)用 response.write: Bypassing Koa's response handling is not supported. Avoid using the following node properties:
但要實(shí)現(xiàn)分片向客戶端發(fā)送數(shù)據(jù),必然還是得調(diào)用 Node.js Http 模塊的 response.write(chunk[, encoding][, callback]) 方法,而這里的 response 就是 ctx.res 或 ctx.response。 所以為什么 Koa 要說不建議直接調(diào)用上述方法操作請(qǐng)求的返回呢,我們來看看 Koa 內(nèi)部對(duì) response 都會(huì)做些什么默認(rèn)的處理。 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);}在應(yīng)用完各種中間件后(fnMiddleware(ctx))通過 handleResponse 對(duì)請(qǐng)求進(jìn)行一些操作,最終是在 respond 函數(shù)里。 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 方法里會(huì)根據(jù)外部是否有設(shè)置過 ctx.body,以及不同的 header 來設(shè)置 ctx.body,最終會(huì)調(diào)用 response.end 來結(jié)束掉本次請(qǐng)求。 注意到如果設(shè)置了 ctx.respond = false,這個(gè)方法就直接 return 了,這是一種跳過這里處理的方式。但其實(shí)如果我們?cè)谥虚g件中手動(dòng)調(diào)用了 ctx.res.end() 后,相當(dāng)于已經(jīng)提前結(jié)束掉請(qǐng)求了,同樣也不會(huì)走 Koa 這里的處理。 所以直接在中間件中調(diào)用 ctx.res.write() 及 ctx.res.end() 就可以實(shí)現(xiàn) chunked 類型的響應(yīng),倒無須對(duì) Koa 做額外設(shè)置。 Koa 實(shí)現(xiàn) chunked 數(shù)據(jù)傳輸根據(jù)上面的分析,及之前一篇關(guān)于HTTP 響應(yīng)的分塊傳輸?shù)奈恼?#xff0c;我們得出以下 Koa 中的實(shí)現(xiàn)邏輯: 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}`);運(yùn)行效果: Koa 中實(shí)現(xiàn) chunked 響應(yīng)的運(yùn)行效果 如你所見,Koa 中的這個(gè)實(shí)現(xiàn)會(huì)在調(diào)用 ctx.res.end() 后將本來應(yīng)該在頁面內(nèi)容中處于最頂部的內(nèi)容,移動(dòng)到最底部。不解。 或者通過 curl 在命令行中查看效果: $ curl -N http://localhost:3000命令行中接收 chunked 數(shù)據(jù)的效果 示例代碼可在 wayou/koa-chunked-response 找到。 相關(guān)資源
|
轉(zhuǎn)載于:https://www.cnblogs.com/Wayou/p/koa_transfer_encoding_chunked.html
總結(jié)
以上是生活随笔為你收集整理的Koa 中实现 chunked 数据传输的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 孕妇梦到韭菜是什么意思
- 下一篇: 做梦梦到钱和屎是什么意思