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.pswp.cn/news/393464.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393464.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393464.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git 短寫設置_如何在短短幾分鐘內設置一個Git客戶端

git 短寫設置Today we’re going to talk about Git. You’re going to learn what Git is and how to set up a Git client on your computer.今天我們將討論Git。 您將學習什么是Git&#xff0c;以及如何在計算機上設置Git客戶端。 什么是Git&#xff1f; (What is Git?) I…

P1977 出租車拼車

P1977 出租車拼車 題目背景 話說小 x 有一次去參加比賽&#xff0c;雖然學校離比賽地點不太遠&#xff0c;但小 x 還是想坐 出租車去。大學城的出租車總是比較另類&#xff0c;有“拼車”一說&#xff0c;也就是說&#xff0c;你一個人 坐車去&#xff0c;還是一堆人一起&#…

leetcode1011. 在 D 天內送達包裹的能力(二分查找)

傳送帶上的包裹必須在 D 天內從一個港口運送到另一個港口。 傳送帶上的第 i 個包裹的重量為 weights[i]。每一天&#xff0c;我們都會按給出重量的順序往傳送帶上裝載包裹。我們裝載的重量不會超過船的最大運載重量。 返回能在 D 天內將傳送帶上的所有包裹送達的船的最低運載…

java集合概念_JAVA集合概念

Java集合是使程序能夠存儲和操縱元素不固定的一組數據。 所有Java集合類都位于java.uti包中。與Java數組不同&#xff0c;Java集合中不能存放基本數據類型&#xff0c;只能存放對象的引用。但是在JDK5.0以后的版本當中&#xff0c;JAVA增加了“自動裝箱”和“自動拆箱”的機制&…

項目計劃總結

項目計劃總結 任務 日期 聽課&#xff08;min&#xff09; 編程&#xff08;min&#xff09; 閱讀課本&#xff08;min&#xff09; 日總結&#xff08;min&#xff09; 2017/3/13 120 70 190 2017/3/14 80 80 2017/3/15 90 30 120 2017/3/16 …

HTML5新特性之Mutation Observer

Mutation Observer&#xff08;變動觀察器&#xff09;是監視DOM變動的接口。當DOM對象樹發生任何變動時&#xff0c;Mutation Observer會得到通知。 要概念上&#xff0c;它很接近事件。可以理解為&#xff0c;當DOM發生變動會觸發Mutation Observer事件。但是&#xff0c;它與…

leetcode230. 二叉搜索樹中第K小的元素(中序遍歷)

給定一個二叉搜索樹&#xff0c;編寫一個函數 kthSmallest 來查找其中第 k 個最小的元素。說明&#xff1a; 你可以假設 k 總是有效的&#xff0c;1 ≤ k ≤ 二叉搜索樹元素個數。示例 1:輸入: root [3,1,4,null,2], k 13/ \1 4\2 輸出: 1解題思路 變量 cnt:統計已經按序遍…

Python操作MongoDB - 極簡教程

2019獨角獸企業重金招聘Python工程師標準>>> Python 連接 MongoDB 安裝PyMongo模塊 pip install pymongo使用MongoClient建立連接 from pymongo import MongoClient # 以下為三種建立連接的方式 #client MongoClient() #client MongoClient(localhost, 27017) #cl…

nuxt.js的核心代碼_Nuxt.js中的通用應用程序代碼結構

nuxt.js的核心代碼by Krutie Patel通過克魯蒂帕特爾(Krutie Patel) Nuxt.js中的通用應用程序代碼結構 (Universal application code structure in Nuxt.js) Nuxt.js中的源代碼結構的簡要摘要 (A brief summary of source code structure in Nuxt.js) Are you new to the Nuxt.…

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…

leetcode29. 兩數相除(位運算)

給定兩個整數&#xff0c;被除數 dividend 和除數 divisor。將兩數相除&#xff0c;要求不使用乘法、除法和 mod 運算符。 返回被除數 dividend 除以除數 divisor 得到的商。 整數除法的結果應當截去&#xff08;truncate&#xff09;其小數部分&#xff0c;例如&#xff1a;…

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

為什么80%的碼農都做不了架構師&#xff1f;>>> 導入maven項目 設置maven(全局) 為了不然才轉idea的碼友們重復我犯過的錯&#xff0c;我這兒截圖步驟說明下&#xff1a; 這里是列表文本這里是列表文本idea的設置有兩種&#xff1a;全局&#xff0c;局部(我這么叫的…

node.js web框架_使用Node.js進行Web爬取的終極指南

node.js web框架So what’s web scraping anyway? It involves automating away the laborious task of collecting information from websites.那么&#xff0c;什么是網絡抓取&#xff1f; 它涉及自動化從網站收集信息的艱巨任務。 There are a lot of use cases for web s…

java局部內部類 final_Java的局部內部類以及final類型的參數和變量

Thinking In Java里面的說法(***正確的說法)&#xff1a; 如果定義一個匿名內部類&#xff0c;并且希望它使用一個在其外部定的對象&#xff0c;那么編譯器會要求其參數引用是final 的。publicclassTester {publicstaticvoidmain(String[] args) {A a newA();C c newC();c.shou…

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極大地提高了開發效率、擴大了開源項目的參與度、 增強了版本控制系統…

強化學習簡介

by ADL通過ADL Reinforcement Learning is an aspect of Machine learning where an agent learns to behave in an environment, by performing certain actions and observing the rewards/results which it get from those actions.強化學習是機器學習的一個方面&#xff0…

leetcode1111. 有效括號的嵌套深度(棧)

給你一個「有效括號字符串」 seq&#xff0c;請你將其分成兩個不相交的有效括號字符串&#xff0c;A 和 B&#xff0c;并使這兩個字符串的深度最小。 不相交&#xff1a;每個 seq[i] 只能分給 A 和 B 二者中的一個&#xff0c;不能既屬于 A 也屬于 B 。 A 或 B 中的元素在原字…

利用Arcgis for javascript API繪制GeoJSON并同時彈出多個Popup

1.引言 由于Arcgis for javascript API不可以繪制Geojson&#xff0c;并且提供的Popup一般只可以彈出一個&#xff0c;在很多專題圖制作中&#xff0c;會遇到不少的麻煩。因此本文結合了兩個現有的Arcgis for javascript API擴充庫&#xff0c;對其進行改造達到繪制Geojson并同…