` 与响应流事件编写 Node.js HTTP 客户端)
教程CLI【免费下载链接】learnyounodeLearn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops.项目地址https://gitcode.com/gh_mirrors/le/learnyounode点击查看免费下载本篇技术指南围绕 learnyounode 仓库中的 HTTP CLIENT 练习韩文版说明见 exercises/http_client/problem.ko.md英文原版见 exercises/http_client/problem.md展开完整讲解如何用 Node.js 内置的http核心模块编写一个接收命令行 URL 参数、发起 HTTP GET 请求并把响应内容逐行输出到 stdout 的命令行程序。读完本文你将掌握http.get()的调用签名与回调形态、Node 流对象Stream的事件模型data/error/end、setEncoding()的用法以及 learnyounode 如何自动起一个测试 HTTP 服务器来校验你的代码。练习目标第一个真正的 HTTP 客户端该练习要求你创建一个http-client.js文件编写一个程序对命令行第一个参数传入的 URL 发起 HTTP GET 请求从响应中读取字符串内容并把每一次data事件的字符串内容各占一行输出到控制台stdout。也就是说响应体被分成多个数据块chunk到达时每一块都要单独打一行而不是等到全部接收完毕再一次性输出。这要求你以事件驱动的方式消费响应而不是同步地取回整个响应体。前置知识http核心模块本练习明确指定使用 Node.js 的http核心模块无需安装任何第三方依赖。仓库为此在 docs-nodejs/http.html 中随项目内置了一份 Node.js v12.10.0 的官方http模块文档快照方便学习者在本地随时查阅http.get()、http.request()、响应对象等 API 细节。从仓库结构上看该练习属于 learnyounode 的第七个关卡见 learnyounode.js 中addAll列表的HTTP CLIENT条目它承接了前面基于fs、path的 I/O 练习是整套课程里第一个真正面向网络编程TCP/HTTP的关卡为后续的HTTP COLLECT、JUGGLING ASYNC、TIME SERVER、HTTP FILE SERVER、HTTP UPPERCASERER和HTTP JSON API SERVER等网络练习打下基础。使用http.get()发起 GET 请求http.get()是 Node.js 对简单 GET 请求的便捷封装它等价于http.request()并在内部自动调用req.end()因此不需要手动结束请求。它的两个参数是参数含义第一个参数要 GET 的 URL通常是http://host:port/path形式的字符串第二个参数回调函数在收到响应时被调用与普通的 Node 回调风格function (err, result)不同http.get()的回调签名是function callback (response) { /* ... */ }回调的唯一参数response就是服务端返回的响应对象。注意这里没有err参数错误不是通过回调的第一参数传递的而是通过返回的请求对象和response流上派发的error事件来传递后文会展开。理解response对象Node 流与事件response对象是一个 NodeStream流对象。流是可以像事件发射器一样对待的对象——它会在数据到达、出错、结束时向外派发事件。对于本练习最值得关注的事件有三个事件触发时机data有一块数据可用且可处理时触发回调收到当前数据块error传输过程中发生错误时触发end响应数据全部接收完毕、流结束时触发监听事件的标准写法response.on(data, function (data) { /* ... */ })data事件是流的核心每当底层数据源送来一块数据回调就会执行一次。数据块的大小取决于底层数据源——网络包的大小、服务器端的写入节奏等都会影响每一块数据的字节数因此你无法预先假定每块数据对应一行文本这正是练习要求每个 data 事件单独输出一行的原因它考验的是对事件粒度的直接感知。setEncoding(utf8)让data事件直接给出字符串默认情况下data事件回调收到的data是 Node 的Buffer对象二进制数据需要手动调用data.toString()之类的方法才能转成字符串。但http.get()返回的response流自带setEncoding()方法response.setEncoding(utf8)以utf8调用该方法后data事件就会直接派发String而不是Buffer省去显式转换的步骤代码更简洁、输出更直接。参考解答仓库在 exercises/http_client/solution/solution.js 中给出了官方参考解答仅 8 行把本练习的四个知识点全部浓缩其中use strict const http require(http) http.get(process.argv[2], function (response) { response.setEncoding(utf8) response.on(data, console.log) response.on(error, console.error) }).on(error, console.error)逐行拆解process.argv[2]命令行第一个参数即练习传入的 URLhttp.get(url, callback)发起 GET 请求response.setEncoding(utf8)让后续data事件直接产出字符串response.on(data, console.log)把每个数据块各占一行打印到 stdout——console.log自带换行恰好满足每个 data 事件输出到新行的要求response.on(error, console.error)打印响应流上的错误.on(error, console.error)请求对象本身也可能出错如 DNS 解析失败、连接被拒绝因此需要在http.get()返回的请求对象上再挂一个错误监听形成双重防御。一个等价但显式声明回调函数的变体对应测试文件 test/http_client/valid_01.js 中的写法如下它把响应处理逻辑抽成具名函数逻辑完全一致require(http).get(process.argv[2], processResponse) function processResponse (res) { res.setEncoding(utf8) res.on(data, console.log) res.on(error, console.error) }仓库如何校验你的程序测试服务器的设计考验时序的事件驱动本练习的验证逻辑在 exercises/http_client/exercise.js 中实现值得深读。它用http.createServer()起一个本地测试服务器然后通过setTimeout以每 25 毫秒一个词的节奏把lib/words.js中的单词逐个res.write()出去全部写完才res.end();(function next (i) { if (i words.length) { return res.end() } res.write(words[i].trim()) setTimeout(next.bind(null, i 1), 25) }(0))这个设计的用意在于响应体不是一次性送达的而是被刻意拆成多个小块、跨时间片发送。只有正确监听data事件并逐块输出的程序才能忠实地把每一块内容各自打成一行如果只是等待end后一次性拼接再输出行为就会与预期不一致。也就是说这个测试服务器本身就在逼你采用事件驱动的流式消费方式。测试单词来自 lib/words.js它从boganipsum依赖中取词并随机抽取 10 个。服务器监听随机端口后把完整 URLhttp://localhost:port作为命令行第一个参数传给被验证的子进程this.submissionArgs [url] this.solutionArgs [url]同时服务器在处理完验证后由exercise.addCleanup负责关闭确保测试进程不会悬挂。运行与验证方式在 learnyounode 交互菜单中选中HTTP CLIENT韩文界面中显示为HTTP 클라이언트见 i18n/ko.json然后创建http-client.js并执行验证命令$ learnyounode verify http-client.js验证器会同时运行你的程序和官方解答并比较两者的输出。如果每个data事件的内容没有各自换行、或错误处理不完整比如请求对象上的error监听缺失导致连接失败时进程崩溃都会导致 FAIL 并给出失败原因。此外也可以用node http-client.js url直接手动运行你的程序来观察输出效果。延伸这是整个 HTTP 练习系列的第一环理解本练习的流事件模型后可以顺势挑战后续关卡HTTP COLLECTexercises/http_collect/problem.md反过来要把多个data块拼成完整响应体再输出需要自己管理累计缓冲涉及对end事件的配合使用JUGGLING ASYNCexercises/juggling_async/problem.md并发请求多个 URL 并按顺序输出结果把事件驱动与异步协调组合起来之后的TIME SERVER、HTTP FILE SERVER等则切换到服务器端用http.createServer()与net模块编写服务程序。这些练习与本关卡共同构成 learnyounode 网络编程训练的完整链条课程全貌见 learnyounode.js。赞分享教程CLI【免费下载链接】learnyounodeLearn You The Node.js For Much Win! An intro to Node.js via a set of self-guided workshops.项目地址https://gitcode.com/gh_mirrors/le/learnyounode点击查看免费下载相关推荐nextjs-use-php 对比 react-use-c 与 react-use-rust在 React 中嵌入多语言的 3 种思路nextjs use php 对比 react use c 与 react use rust在 React 中嵌入多语言的 3 种思路 nextjs use教程CLIlearnyounode HTTP CLIENT 练习详解用 Node.js 的 http.get() 编写第一个 HTTP GET 客户端learnyounode HTTP CLIENT 练习详解用 Node.js 的 http.get 编写第一个 HTTP GET 客户端 本指南围绕 lear教程CLIlearnyounode 实战用 http.get() 与 Stream 事件模型编写 HTTP 客户端learnyounode 实战用 http.get 与 Stream 事件模型编写 HTTP 客户端 本文以 learnyounode 课程第 7 个练习 H教程CLI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考