ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

learnyounode 实战:使用 fs.readdir 与 path.extname 实现按扩展名过滤的异步目录列表(filtered_ls 练习详解)

learnyounode 实战:使用 fs.readdir 与 path.extname 实现按扩展名过滤的异步目录列表(filtered_ls 练习详解) 教程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 工作坊中的FILTERED LS按扩展名过滤的目录列表练习为切入点讲解如何编写一个从命令行接收目录路径与扩展名参数、并以非同步asynchronousI/O方式读取目录、按文件扩展名过滤后逐行输出的 Node.js 程序。读完本文后你将掌握fs.readdir()的回调式用法、path.extname()的扩展名判定技巧、process.argv的参数解析规则并能通过 learnyounode 内置的自动验证机制learnyounode verify确认自己的实现符合全部约束。一、练习目标与验收标准该练习对应的任务定义在 exercises/filtered_ls/problem.zh-tw.md英文版见 exercises/filtered_ls/problem.md要求编写一个名为filtered-ls.js的程序输入程序的第一个命令行参数是目录路径例如/path/to/dir/第二个参数是用于过滤的扩展名例如txt过滤规则只输出目录内以.txt结尾的普通文件。注意第二个参数不会预先带有「.」也就是说你拿到的是txt需要在代码中自行拼出.txt输出格式文件列表打印到标准输出console一个文件一行硬性约束必须使用异步asynchronousI/O读取目录禁止使用fs.readdirSync()之类的同步版本——这正是本练习乃至整个 learnyounode 前半段课程想强化的核心观念。此外还有一个容易踩坑的细节程序接收到的参数并非process.argv数组的前两位因为 Node 会把这前两个值保留给系统信息使用第一位是 Node 可执行文件路径第二位是脚本文件路径。真正的外部参数从process.argv[2]才开始这一点在英文原题中特别提示繁体中文版虽未逐字强调但解决方案中正是这样取值的。二、核心 API 讲解2.1fs.readdir()异步读取目录fs模块的readdir()方法完整 API 见 docs-nodejs/fs.html第一个参数是路径名第二个参数是回调函数回调签名固定为function callback (err, list) { /* ... */ }其中err读取失败时的错误对象例如目录不存在、权限不足成功时为nulllist由文件名字符串组成的 Array注意它只包含条目名称不含父目录路径前缀是否含子目录取决于文件系统实现但本练习的测试目录中全部是普通文件。回调式 API 与同步版本fs.readdirSync()的关键区别在于同步版本会阻塞事件循环直到读取完成而异步版本把 I/O 交给底层线程池执行完成后通过事件循环调度回调因此不会阻塞其它并发任务。这正是本练习要求使用异步 I/O 的原因。2.2path.extname()提取扩展名path模块的extname()方法文档见 docs-nodejs/path.html接收一个路径字符串返回从最后一个.含到路径末尾的部分即扩展名。例如path.extname(learnyounode.txt)→.txtpath.extname(learnyounode.dat)→.datpath.extname(README.md)→.mdpath.extname(data.json)→.json由于extname()返回的扩展名自带前导点而命令行参数如txt不带点因此标准做法是把参数拼成. ext后再与之比较。三、参考解决方案逐行拆解learnyounode 在 exercises/filtered_ls/solution/solution.js 提供了官方参考实现全文如下use strict const fs require(fs) const path require(path) const folder process.argv[2] const ext . process.argv[3] fs.readdir(folder, function (err, files) { if (err) return console.error(err) files.forEach(function (file) { if (path.extname(file) ext) { console.log(file) } }) })逐行解读use strict开启严格模式避免隐式全局变量等陷阱引入模块fs负责目录读取path负责扩展名提取参数解析process.argv[2]是目录路径process.argv[3]是扩展名ext提前拼上.把「参数不带点」与「extname返回带点」这两套约定统一起来回调式fs.readdir读取成功后遍历files数组用path.extname(file) ext做严格相等比较命中则console.log(file)逐行输出错误处理回调的第一个参数err非空时立即打印错误并退出return同时防止继续执行后续代码。学习过前面练习如 my_first_io的读者会发现这是典型的「异步回调 提前返回」错误处理模式也是后续 HTTP、Stream 练习中反复出现的基本形态。四、另一种常见写法filter forEach官方测试用例中提供了一种更「函数式」的等价实现见 test/filtered_ls/valid_01.jsconst fs require(fs) const path require(path) fs.readdir(process.argv[2], function (err, list) { if (err) { console.log(err) } list.filter(function (file) { return path.extname(file) . process.argv[3] }).forEach(function (file) { console.log(file) }) })它把「筛选」与「输出」两个步骤拆开先用Array.prototype.filter提取出扩展名匹配的文件子集再用forEach逐行打印。两种写法在语义上等价均能通过验证差别仅在于filter写法先构造新数组再遍历在文件数量极大时会有一次额外拷贝但本练习场景完全无需顾虑。你可以根据自己更习惯的风格选择。五、验证机制verify 到底在检查什么learnyounode 的每个练习都有一套自动验证逻辑理解它有助于你写出恰好满足全部约束的代码。本练习的验证器定义在 exercises/filtered_ls/exercise.js工作流程如下5.1 搭建测试环境验证开始前addSetup会在系统临时目录中创建名为_learnyounode_进程号的测试目录并依据 exercises/filtered_ls/file-list.json 中的文件清单写入一批内容为nothing to see here的测试文件。该清单包含[ learnyounode.dat , learnyounode.txt , learnyounode.sql , api.html , README.md , CHANGELOG.md , LICENCE.md , md , data.json , data.dat , words.dat , w00t.dat , w00t.txt , wrrrrongdat , dat ]注意最后三个条目wrrrrongdat、dat这类文件名没有任何扩展名path.extname返回空字符串它们正是用来检验你的过滤逻辑是否足够严谨的「陷阱文件」而md这个条目连点都没有也在考验程序不会误判。随后验证器会把测试目录路径与md这个扩展名分别追加到待提交程序与官方 solution 的命令行参数末尾通过submissionArgs.unshift(...)注入保证两者以完全相同的输入运行。5.2 校验必须使用异步 I/O验证器通过 exercises/my_first_io/wrap.js 中的wrapFsCalls机制在子进程中包裹monkey-patch所有fs方法每当待提交程序调用任意 fs 方法时都会记录方法名到ctx.fsCalls。随后addVerifyProcessor遍历这些调用记录并执行两条判定若发现任何以Sync结尾的调用如readdirSync输出fail.sync失败信息——即使用了同步 I/O直接判负若存在非同步的 fs 调用输出pass.async通过信息若既没有同步调用也没有异步调用输出fail.unused——说明你连fs模块都没用到。最终只有当usedAsync !usedSync成立时验证才整体通过。这从机制上保证了「必须异步」不是一句口号。5.3 反例对照仓库的 test/filtered_ls/ 目录给出了完整的三类样本你可以直接运行它们观察验证器行为test/filtered_ls/valid_01.js标准异步实现验证应通过test/filtered_ls/invalid_01.js使用了fs.readdirSync验证应因同步 I/O 失败test/filtered_ls/invalid_02.js通过child_process.exec(ls -1 ...)调用系统命令实现虽然结果输出看起来正确但没有直接使用fs.readdir不符合练习要求的 API 使用方式同样无法通过验证。六、运行与验证命令完成filtered-ls.js后先用命令行手动跑一遍看输出是否符合预期目录与扩展名可自行替换node filtered-ls.js /some/path txt再交给 learnyounode 自动验证learnyounode verify filtered-ls.js运行该命令后learnyounode 会按照第 5 节的流程搭建测试目录、以md为扩展名运行你的程序并同时运行官方 solution 比对输出。输出逐行一致且未使用同步 API 时你会看到 PASS否则会得到包含 FAIL 原因同步调用、未使用 fs、输出不匹配等的提示修改后重新执行 verify 即可。需要注意的是{appname}是 learnyounode 在题目文案中使用的占位符实际执行时应替换为全局安装的learnyounode命令。若尚未安装可通过npm install -g learnyounode完成全局安装后启动。七、延伸思考如何顺带处理目录项中的子目录本练习只要求按扩展名过滤文件名若需区分普通文件与目录可在fs.readdir回调内结合fs.stat或fs.Direntreaddir的withFileTypes选项进一步判断错误处理的分支官方 solution 用console.error(err)输出错误你也可以选择更显式的process.exitCode 1配合错误日志这在真实 CLI 工具中更常见通向下一关本练习是 learnyounode「文件系统与异步 I/O」系列的重要一环掌握回调式fs.readdir之后接下来的 MAKE IT MODULAR 练习会要求把这段过滤逻辑抽成独立模块并暴露module.exports导出接口练习的模块验证测试见 exercises/make_it_modular/ 目录会直接检查导出的函数签名与调用方式。八、核心要点速览要点说明参数位置目录路径取process.argv[2]扩展名取process.argv[3]前两位被 Node 系统信息占用扩展名拼接命令行参数不带点需拼成. ext后再与path.extname(file)比较读取方式必须使用fs.readdir(path, callback)禁止*Sync系列方法输出格式命中文件用console.log(file)逐行输出一行一个错误处理回调首个参数err非空时打印错误并return自动验证learnyounode verify filtered-ls.js验证器会监控 fs 调用是否为异步并比对输出掌握上述六点你的实现就能稳定通过 FILTERED LS 练习的自动验证并为后续学习 Node.js 文件系统操作、模块化设计与网络编程打下坚实基础。相关 API 的完整参考可继续查阅仓库内的 docs-nodejs/fs.html 与 docs-nodejs/path.html。赞分享教程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点击查看免费下载相关推荐influence-release部署指南在真实项目中应用影响函数分析influence release部署指南在真实项目中应用影响函数分析 influence release是一个基于影响函数Influence Functi教程CLIlearnyounode 练习五filtered_ls 异步目录过滤实战指南learnyounode 练习五filtered_ls 异步目录过滤实战指南 本指南围绕 learnyounode 开源练习项目中的 filtered_ls教程CLISwiftCrossUI 项目常见问题解决方案SwiftCrossUI 项目常见问题解决方案 SwiftCrossUI 是一个开源项目旨在提供一个跨平台的声明式 UI 框架灵感来自于 SwiftUI。该教程CLI上一篇Redux-Offline在微前端架构中的应用跨应用状态管理终极指南下一篇Salt Player 音频渲染引擎对比OpenSL ES vs AAudio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表