Koa 中实现 chunked 数据传输

有关于 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 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 中实现 chunked 响应的运行效果

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

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

$ curl -N http://localhost:3000

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

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

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

相关资源

  • wayou/koa-chunked-response
  • Koa documentation
  • Node.js Docs - response.write(chunk[, encoding][, callback])
  • Node.js Docs - response.end([data][, encoding][, callback])

转载于:https://www.cnblogs.com/Wayou/p/koa_transfer_encoding_chunked.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML5新特性之Mutation Observer

Mutation Observer&#xff08;变动观察器&#xff09;是监视DOM变动的接口。当DOM对象树发生任何变动时&#xff0c;Mutation Observer会得到通知。 要概念上&#xff0c;它很接近事件。可以理解为&#xff0c;当DOM发生变动会触发Mutation Observer事件。但是&#xff0c;它与…

Python操作MongoDB - 极简教程

2019独角兽企业重金招聘Python工程师标准>>> Python 连接 MongoDB 安装PyMongo模块 pip install pymongo使用MongoClient建立连接 from pymongo import MongoClient # 以下为三种建立连接的方式 #client MongoClient() #client MongoClient(localhost, 27017) #cl…

java 省市区三级联动_AJAX省市区三级联动下拉菜单(java版)

此小程序的功能主要是采用异步请求方式从数据库中调取省市区信息显示到下拉列表&#xff1a;代码如下&#xff1a;建立数据库中的代码和一些配置文件信息就省略了&#xff0c;主要有JavaScript中的代码为&#xff1a;$(document).ready(function(){$.get("getProvince.do&…

20155305乔磊2016-2017-2《Java程序设计》第四周学习总结

20155305乔磊2016-2017-2《Java程序设计》第四周学习总结 教材学习内容总结 继承 继承就是避免多个类间重复定义共同行为。面向对象中&#xff0c;子类继承父类&#xff0c;就是把程序中相同的代码部分提升为父类。extends关键字&#xff0c;表示前者会扩充后者的行为&#xff…

【eclipse转idea的第一天】配置idea

为什么80%的码农都做不了架构师&#xff1f;>>> 导入maven项目 设置maven(全局) 为了不然才转idea的码友们重复我犯过的错&#xff0c;我这儿截图步骤说明下&#xff1a; 这里是列表文本这里是列表文本idea的设置有两种&#xff1a;全局&#xff0c;局部(我这么叫的…

Vmware 安装虚拟工具 (二)

打开虚拟机&#xff0c;以root超级用户登陆&#xff0c;菜单栏选择虚拟机&#xff0c;install安装虚拟机 拷贝虚拟工具到 在根目录下建立文件夹&#xff0c;并将工具拷贝到该文件夹&#xff0c;例如vmtool 打开终端&#xff0c;进入该目录开始安装 如图&#xff0c;进入目录解压…

git与svn的区别 ?Git 与 SVN那个更好?

git与svn的区别 &#xff1a; http://www.360doc.com/content/12/1228/20/11220452_256857021.shtml 在版本控制系统的选型上&#xff0c;是选择Git还是SVN&#xff1f; 对于开源项目来说这不算问题。使用Git极大地提高了开发效率、扩大了开源项目的参与度、 增强了版本控制系统…

利用Arcgis for javascript API绘制GeoJSON并同时弹出多个Popup

1.引言 由于Arcgis for javascript API不可以绘制Geojson&#xff0c;并且提供的Popup一般只可以弹出一个&#xff0c;在很多专题图制作中&#xff0c;会遇到不少的麻烦。因此本文结合了两个现有的Arcgis for javascript API扩充库&#xff0c;对其进行改造达到绘制Geojson并同…

HBase数据备份及恢复(导入导出)的常用方法

一、说明 随着HBase在重要的商业系统中应用的大量增加&#xff0c;许多企业需要通过对它们的HBase集群建立健壮的备份和故障恢复机制来保证它们的企业&#xff08;数据&#xff09;资产。备份Hbase时的难点是其待备份的数据集可能非常巨大&#xff0c;因此备份方案必须有很高的…

Android商城开发系列(二)——App启动欢迎页面制作

商城APP一般都会在应用启动时有一个欢迎界面&#xff0c;下面我们来实现一个最简单的欢迎页开发&#xff1a;就是打开商城App&#xff0c;先出现欢迎界面&#xff0c;停留几秒钟&#xff0c;自动进入应用程序的主界面。 首先先定义WelcomeActivity布局&#xff0c;布局非常简单…

DELL安装不了mysql_Windows 版本 Mysql 8.x 安装

1、官网下载安装包百度网盘链接&#xff1a;https://pan.baidu.com/s/1cFRbQM5720xrzMxbgjPeyA提取码&#xff1a;xlz72、解压安装包并新建一个文件夹作为安装目录(mysqlInstall)3、配置 Mysql 环境变量4、在解压好的目录下新建一个 my.ini 文件(注意&#xff1a;my.ini 文件和…

Hyper-V Server联机调整虚拟硬盘大小

1. 技术概述&#xff1a; 从 Windows Server 2012 R2开始&#xff0c;管理员可以在运行虚拟机的同时&#xff0c;使用 Hyper-V 来扩展或压缩虚拟硬盘的大小。存储管理员可以通过对运行中的虚拟硬盘执行维护操作来避免代价不菲的停机。不再需要关闭虚拟机&#xff0c;这可以避免…

python网络爬虫(5)BeautifulSoup的使用示范

创建并显示原始内容 其中的lxml第三方解释器加快解析速度 import bs4 from bs4 import BeautifulSoup html_str """ <html><head><title>The Dormouses story</title></head> <body> <p class"title"><…

物联网笔记

转载于:https://www.cnblogs.com/16-C-kai/p/6596682.html

关于大学生玩网络游戏的调查问卷

1.创建问卷&#xff0c;输入调查名称 2编辑问卷 3检查问卷&#xff0c;是否有误 4.提交并发布问卷 5分享问卷 6.问卷分析 转载于:https://www.cnblogs.com/dzw1996/p/7786754.html

第六次 实验

转载于:https://www.cnblogs.com/P201821440005/p/10967987.html

du命令、df命令用法

一、du命令 [plain] view plaincopy print?[rootwc1 mysql]# du --help Usage: du [OPTION]... [FILE]... or: du [OPTION]... --files0-fromF Summarize disk usage of each FILE, recursively for directories. Mandatory arguments to long options are mandatory…

SQL Server 2008 - Cannot set a credential for principal 'sa'.

很久没有用到SQL Server了&#xff0c;今天有幸在帮同事解决一个SQL Server数据连接的问题时突然发现我无法修改我的sa用户的密码了。过程是这样的&#xff1a;一开始我本地的数据库实例是Windows认证方式&#xff0c;我想将它改成Windows和数据库混合认证方式后用sa账户登录&a…

Java小知识-----Map 按Key排序和按Value排序

Map排序的方式有很多种&#xff0c;这里记录下自己总结的两种比较常用的方式&#xff1a;按键排序(sort by key)&#xff0c; 按值排序(sort by value)。 1、按键排序 jdk内置的java.util包下的TreeMap<K,V>既可满足此类需求&#xff0c;向其构造方法 TreeMap(Comparator…

Microsoft Deployment Toolkit 2010 新功能实战之一

续Microsoft Deployment Toolkit 2010 Beta 2先睹为快&#xff01;下面将通过使用Microsoft Deployment Toolkit 2010来部署Windows 7来介绍它的新功能的具体操作。有些概念的理解和操作方法参见MDT2008部署之一概览。 一、实验环境操作全部在VMware Workstation的虚拟操作环境…