有关于 Transfer-Encoding:chunked 类型的响应,参见之前的文章HTTP 响应的分块传输。这里看 Koa 中如何实现。

Koa 中请求返回的处理

虽然官方文档有描述说明不建议直接调用 response.write

Bypassing Koa's response handling is not supported. Avoid using the following node properties:

  • res.statusCode
  • res.writeHead()
  • res.write()
  • res.end()

但要实现分片向客户端发送数据,必然还是得调用 Node.js Http 模块的 response.write(chunk[, encoding][, callback]) 方法,而这里的 response 就是 ctx.resctx.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 koa
if (false === ctx.respond) return; if (!ctx.writable) return; const res = ctx.res;

let body = ctx.body;

const code = ctx.status; // ignore body

if (statuses.empty[code]) {

// strip headers

ctx.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 body

if (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);

} // responses

if (Buffer.isBuffer(body)) return res.end(body);

if ('string' == typeof body) return res.end(body);

if (body instanceof Stream) return body.pipe(res); // body: json

body = 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(</span>server started at http://localhost:<span class="pl-s1"><span class="pl-pse">${</span><span class="pl-c1">PORT</span><span class="pl-pse">}</span></span><span class="pl-pds">);

运行效果:

Koa 中实现 chunked 响应的运行效果

如你所见,Koa 中的这个实现会在调用 ctx.res.end() 后将本来应该在页面内容中处于最顶部的内容,移动到最底部。不解。

或者通过 curl 在命令行中查看效果:

$ curl -N http://localhost:3000

命令行中接收 chunked 数据的效果

示例代码可在 wayou/koa-chunked-response 找到。

相关资源

Koa 中实现 chunked 数据传输的更多相关文章

  1. iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见

    iOS中关于动态Tableview中的cell数据传输的多线程问题解决之拙见 (2015-12-05 12:48:20)[编辑][删除] 转载▼     首先我们先明确一下问题: 1.因为UI是在主线 ...

  2. Koa与Node.js开发实战(3)——Nunjucks模板在Koa中的应用(视频演示)

    技术架构: ​ 在Koa中应用Nunjucks,需要先把Nunjucks集成为符合Koa规格的中间件(Middleware),从本质上来讲,集成后的中间件的作用是给上下文对象绑定一个render(vi ...

  3. Koa 中 ejs 模板的使用

    ejs的基本使用 安装 koa-views 和 ejs npm install --save koa-views/cnpm install --save koa-views npm install e ...

  4. 从前端中的IOC理念理解koa中的app.use()

    忙里偷闲,打开平时关注的前端相关的网站,浏览最近最新的前端动态.佼佼者,平凡的我做不到,但还是要争取不做落后者. 前端中的IoC理念,看到这个标题就被吸引了.IoC 理念,不认识呢,点击去一看,果然没 ...

  5. koa中返回404并且刷新后才正常的解决方案

    概述 这几天学习koa2,有一些心得,记录下来,供以后开发时参考,相信对其他人也有用. 起因 这几天学习koa2,写的代码执行时有一个奇怪的bug:明明能够返回数据,却有时正常返回数据,有时偏偏给你返 ...

  6. koa 基础(十六)koa 中 session 的使用

    1.app.js /** * koa 中 session 的使用 * 1.npm install koa-session --save * 2.const session = require('koa ...

  7. koa 基础(十一)koa 中 koa-bodyparser 中间件获取表单提交的数据

    1.app.js /** * koa 中 koa-bodyparser 中间件获取表单提交的数据 * 1.npm install --save koa-bodyparser * 2.引入 const ...

  8. koa 基础(十)原生node.js 在 koa 中获取表单提交的数据

    1.app.js // 引入模块 const Koa = require('koa'); const router = require('koa-router')(); /*引入是实例化路由 推荐*/ ...

  9. Cookie、Session、JWT在koa中的应用及实现原理

    目录 Cookie 重要属性 实现原理 cookie签名实现原理 注意事项 Session 实现原理 JWT 使用方式 组成 实际应用 实现原理 前端存储方式 cookie session local ...

随机推荐

  1. MacOS 升级后pod 出现的问题

    -bash: /usr/local/bin/pod: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: bad ...

  2. Vs工程高版本向低版本迁移

    使用到一个SLAM程序,一些运行库是基于PCL1.7.2Vs11版本,但是Vs11巨慢,应该把程序迁移到Vs10 下面,遇到打不开的问题. 1.修改方法: 参考链接:使用低版本打开高版本VS解决方案 ...

  3. 用了那么多项目管理工具,还是CORNERSTONE这款最好用

    在与软件开发有关的项目,往往会出现很难管理情况.许多事情都需提前计划.控制与管理,所以许多项目经理很容易迷失在计划的过程中.幸运的是,市场上提供了各种各样的项目管理工具.但不幸的是,工具实在是太多了. ...

  4. BZOJ 3531: [Sdoi2014]旅行 权值线段树 + 树链剖分

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

  5. 卸载hyper-v后 仍然提示 vmware 与 hyper-v 不兼容

    已经卸载了hyper-v 仍然提示 vmware 与 hyper-v 不兼容:天天模拟器,提示VT模式没有开启,BIOS里面已经设置过了 环境win10,vm的失败和模拟器的失败都是hyper-v冲突 ...

  6. HTTP数据包详解

     无论Web技术在未来如何发展,理解Web程序之间通信的基本协议相当重要, 因为它让我们理解了Web应用程序的内部工作. 本文将对HTTP协议进行详细的实例讲解,内容较多,希望大家耐心看. 阅读目录 ...

  7. PAT_A1141#PAT Ranking of Institutions

    Source: PAT A1141 PAT Ranking of Institutions (25 分) Description: After each PAT, the PAT Center wil ...

  8. Skyline Web 端数据浏览性能优化

    三维数据的效率一直是个瓶颈,特别是在Web端浏览一直是个问题,在IE内存限制1G的条件下,对于三维数据动不动几十G的数据量,这1G显得多么微不足道.虽然现在三维平台都是分级加载,或者在程序中采用数据分 ...

  9. css画圆

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...

  10. MySQL7.5.15数据库配置主从服务器实现双机热备实例教程

    环境说明 程序在:Web服务器192.168.0.57上面 数据库在:MySQL服务器192.168.0.67上面 实现目的:增加一台MySQL备份服务器(192.168.0.68),做为MySQL服 ...