当前位置: 首页 > java >正文

学习记录:DAY33

前端学习之旅:Node.js 模块与 HTTP 服务

前言----------------------------------------
又是许久许久没有更新,在苦哈哈弄完期末,然后花一天时间把计算机网络课设写了之后。现在又即将回到前后端学习的状态。我想现在正处于一个调整期的状态。一个是随着 blog 的不断堆积,有必要把它们整理成更具有逻辑性的知识片。另一个是我需要了解当前前后端需要学习的路线,这样我可以有一个更明确地学习规划。言不在多,开始工作吧!


日程----------------------------------------
以后不能熬太多夜了,今天又是 9 点多起的床,这样太消耗身体了。今天早上的任务是整理 blog 的内容。又弄了一下午的课设,在我不懈努力之下,我终于是选择了放弃,麻了。
-----------6.23-------------
今天开始学 Nodejs,学了 buffer 和 fs 模块,来写写 blog
一放假早上就起不来了,得慢慢把时差调回来
晚上七点半了,把 http 模块学得差不多了,做做 blog


学习内容----------------------------------------

省流

  1. 分享一下近期有价值的内容
  2. Nodejs buffer 模块
  3. Nodejs fs 模块
  4. Nodejs http 模块

1. 分享一下近期有价值的内容

  • 用于学习 git 的可实践网站:Learn Git Branching 是一个非常实用的网站,可以帮助你通过实践来学习 Git 的各种操作。
  • 用于快速搭建虚拟局域网环境:Happynet 是一个基于 N2N 的工具,可以帮助你快速搭建虚拟局域网环境,非常适合需要远程访问和控制设备的场景。

2. Nodejs buffer 模块

用于内存的分配,以下是常见的创建方式:

  • 创建let buf = Buffer.alloc(10);
  • 非安全创建let buf_2 = Buffer.allocUnsafe(10);
  • 基于内容创建let buf_3 = Buffer.from("hello");
  • 获取的 buf 是一个数组let buf_4 = Buffer.from([85, 234, 231, 21, 85, 94]); console.log(buf_4[0].toString());

3. Nodejs fs 模块

用于文件操作,以下是常见的操作:

  • 导入模块const fs = require('fs');
  • 写入文件
    • 异步写入fs.writeFile('./test.txt', 'test12356', err => { if (err == null) { console.log('写入成功'); } });
    • 同步写入fs.writeFileSync('./test.txt', 'test2441');
    • 追加写入fs.appendFile('./test.txt', ',not my test', err => {});
    • 流式写入
      const ws = fs.createWriteStream('./test.txt', { flags: 'a' });
      ws.write("\r\n我");
      ws.write('\r\n是');
      ws.write('\r\n谁?');
      ws.end();
      
  • 异步特性:当程序进行到异步代码块时,会创建一个新线程处理异步代码,程序会继续向下执行。线程处理完异步代码后,通过回调函数压入任务队列中。这种异步特性在 Nodejs 非常常见。
  • 路径问题:使用 __dirname 可以获取当前的执行文件所在目录,通过 path 模块拼接路径:
    const path = require('path');
    const filepath = path.join(__dirname, 'test.txt');
    
  • 额外 API 说明
    API说明
    path.resolve拼接规范的绝对路径 常用
    path.sep获取操作系统的路径分隔符
    path.parse解析路径并返回对象
    path.basename获取路径的基础名称
    path.dirname获取路径的目录名
    path.extname获取路径的扩展名
  • 文件读取
    • 异步读取fs.readFile(filepath, (err, data) => { console.log(data.toString()); });
    • 流式读取
      const rs = fs.createReadStream(filepath);
      rs.on('data', chunk => { console.log(chunk.toString()); });
      
    • 读取 + 写入
      ws = fs.createWriteStream(path.join(__dirname, 'test2.txt'));
      rs.pipe(ws);
      
  • 重命名fs.rename(path.join(__dirname, 'test2.txt'), path.join(__dirname, 'test3.txt'), err => {});
  • 删除
    • fs.unlink(path.join(__dirname, 'test3.txt'), err => {});
    • 在 14.4 版本后添加了 rm 方法,两者的功能类似:fs.rm(path.join(__dirname, 'test3.txt'), err => {});
  • 文件夹操作
    • 创建文件夹fs.mkdir(path.join(__dirname, 'dir1'), err => {});
    • 递归创建fs.mkdir(path.join(__dirname, 'dir2/3/4/5'), { recursive: true }, err => {});
    • 读取文件夹fs.readdir(__dirname, (err, data) => { console.log(data); });
    • 删除文件夹
      • fs.rmdir(path.join(__dirname, 'dir1'), err => {});
      • 递归删除:fs.rm(path.join(__dirname, 'dir2'), { recursive: true }, err => {});
  • 获取资源的信息
    fs.stat(__dirname + '/test.txt', (err, data) => {console.log(data);
    });
    
    获取到的内容:
    Stats {dev: 0,mode: 33206,nlink: 1,uid: 0,gid: 0,rdev: 0,blksize: 4096,ino: 7318349395273121,size: 49,blocks: 0,atimeMs: 1750658164362.0237,mtimeMs: 1750652965429.8325,ctimeMs: 1750656700147.115,birthtimeMs: 1750652121205.9016
    }
    
    可以通过自定义输出来让内容更加格式化:
    fs.stat(__dirname + '/test.txt', (err, stats) => {console.log('文件信息:', {isFile: stats.isFile(), // 是否是文件isDirectory: stats.isDirectory(), // 是否是目录size: stats.size + ' bytes', // 文件大小createdAt: stats.birthtime, // 创建时间(Date 对象)modifiedAt: stats.mtime, // 修改时间(Date 对象)accessedAt: stats.atime, // 访问时间(Date 对象)});
    });
    
    结果如下:
    文件信息: {isFile: true,isDirectory: false,size: '49 bytes',createdAt: 2025-06-23T04:15:21.206Z,modifiedAt: 2025-06-23T04:29:25.430Z,accessedAt: 2025-06-23T05:56:04.362Z
    }
    

4. Nodejs http 模块

通过 Nodejs 来控制 http 相关的请求和响应内容:

  • 启动服务
    const http = require('http');
    const server = http.createServer((req, rep) => {//设置响应头 utf-8rep.setHeader('content-type', 'text/html;charset=utf-8');//设置响应体rep.end('你好');
    });
    server.listen(9000, () => {console.log('服务已经启动');
    });
    
  • 获取请求报文
    含义语法
    请求方法request.method
    请求版本request.httpVersion
    请求路径request.url
    URL 路径require('url').parse(request.url).pathname
    URL 查询字符串require('url').parse(request.url, true).query
    请求头request.headers
    请求体request.on('data', function(chunk){})
    request.on('end', function(){});
    比较常用的是请求方法和请求路径。获取 url 路径:
    const server = http.createServer((req, rep) => {...//实例化 URL 对象let url = new URL(req.url, 'http://127.0.0.1');//输出路径console.log(url.pathname);//输出查询字符串console.log(url.searchParams.get('key'));...
    });
    
    假设现在访问 http://localhost:9000/heyi?key=124,则控制台返回:
    /heyi
    124
    
  • 设置响应报文
    作用语法
    设置响应状态码response.statusCode
    设置响应状态描述response.statusMessage
    设置响应头信息response.setHeader('头名', '头值')
    设置响应体response.write('xx')
    />
    response.end('xxx')
    注意 response.end() 代表了响应处理的结束,会将响应结果返回给网页。一般设置内容用 response.write() 更加灵活一点,将 end 仅作为结尾。响应体是可以设置为一个文件 / 文件流的。通过设置响应体来加载 html 界面:
    const http = require('http');
    const fs = require('fs');
    const server = http.createServer((req, rep) => {let html = fs.readFileSync(__dirname + '/test.html');rep.end(html);
    });
    server.listen(9000, () => {});
    
  • 页面加载基本过程:网页的资源不是一次性全部获取的,以下面的为例子:
    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./test.css">
    </head>
    <body><h1>你好 bro</h1><button index="btn1" class="style">点我</button><script src="test.js"></script>
    </body>
    </html>
    
    首先我们手动加载了 html 资源,当浏览器发现 html 引用了 css,js 等资源时,它会向服务器发送对应的资源请求。如果是像我们之前那种写法,无论什么请求,都获取到了 html 资源,是肯定会出错的。我们需要动态的为资源请求进行相应请求体设置:
    const server = http.createServer((req, rep) => {let { pathname } = new URL(req.url, 'http://127.0.0.1');//拼接文件路径if (req.url == '/') pathname = '/test.html';let filePath = __dirname + pathname;//异步读取资源fs.readFile(filePath, (err, data) => {if (err) {rep.statusCode = 500;rep.end('文件读取失败');return;}rep.end(data);});
    });
    
  • 网页 URL 路径:网页中的 URL 主要分为两大类:相对路径与绝对路径。
    • 绝对路径
      形式特点
      http://atguigu.com/web直接向目标资源发送请求,容易理解。网站的外链会用到此形式
      //atguigu.com/web与页面 URL 的协议拼接形成完整 URL 再发送请求。大型网站用的比较多
      /web与页面 URL 的协议、主机名、端口拼接形成完整 URL 再发送请求。中小型网站
    • 相对路径:相对路径在发送请求时,需要与当前页面 URL 路径进行计算,得到完整 URL 后,再发送请求,学习阶段用的较多。例如当前网页 url 为 http://www.atguigu.com/course/h5.html
      形式最终的 URL
      ./css/app.csshttp://www.atguigu.com/course/css/app.css
      js/app.jshttp://www.atguigu.com/course/js/app.js
      ../img/logo.pnghttp://www.atguigu.com/img/logo.png
      ../../mp4/show.mp4http://www.atguigu.com/mp4/show.mp4
  • 设置资源类型:媒体(MIME)类型是一种标准,用来表示文档、文件或字节流的性质和格式。
    MIME 类型结构例子
    type/[subtype]text/html, text/css, image/jpeg, image/png, application/json
    HTTP 服务可以设置响应头 Content-Type 来表明响应体的 MIME 类型,浏览器会根据该类型决定如何处理响应体。下面是常见文件对应的 MIME 类型:
    文件类型MIME类型
    -------------------------------------
    htmltext/html
    csstext/css
    jstext/javascript
    pngimage/png
    jpgimage/jpeg
    gifimage/gif
    mp4video/mp4
    mp3audio/mpeg
    jsonapplication/json
    基于这个,我们可以自己规范化设置 mine 值:
    const mines = {html: 'text/html',css: 'text/css',js: 'text/javascript'
    };
    const server = http.createServer((req, rep) => {let { pathname } = new URL(req.url, 'http://127.0.0.1');//拼接文件路径if (req.url == '/') pathname = '/test.html';let filePath = __dirname + pathname;//获取文件后缀名 //.txt -> txtlet ext = path.extname(filePath).slice(1);//获取对应的类型let type = mines[ext];if (type) {rep.setHeader('content-type', type + ';charset=utf-8');} else {rep.end('类型获取失败');}//异步读取资源......
    });
    
    事实上,即使没有设置 mine,浏览器的嗅探机制也会根据返回的响应内容进行 mine 的设置。而中文字符集的设置,往往只需要设置 html 界面的,其他资源会基于 html 的字符集进行设置(尽管直接在网页读取资源时仍然是乱码):
    rep.setHeader('content-type', type + ';charset=utf-8');
    
http://www.xdnf.cn/news/14617.html

相关文章:

  • 2025.6.24总结
  • 用 Python 打造立体数据世界:3D 堆叠条形图绘制全解析
  • HTML炫酷烟花
  • 微算法科技开发基于布尔函数平方和表示形式的最优精确量子查询算法
  • NLP基础1_word-embedding
  • 利用大型语言模型增强边缘云 AI 系统安全性
  • AI智能化高效办公:WPS AI全场景深度应用指南
  • qt常用控件--03
  • 重点解析(软件工程)
  • 从零学习linux(2)——管理
  • 2025年检测相机十大品牌测评:工业级精度与场景化解决方案解析
  • DeepSeek今天喝什么随机奶茶推荐器
  • Docker知识点汇总——AI教你学Docker
  • 企业主动风险管理破局供应链“黑天鹅”,善用期货
  • Origin绘制三Y轴柱状图、点线图、柱状点线图
  • Spark基于Bloom Filter算法的Runtime Filter Join优化机制
  • STM32 串口通信②:蓝牙模块HC-05控制单片机
  • 以玄幻小说方式打开深度学习词嵌入算法!! 使用Skip-gram来完成 Word2Vec 词嵌入(Embedding)
  • Maven 多模块项目调试与问题排查总结
  • Elasticsearch 索引文档的流程
  • 酒店住宿自助入住系统——店铺自动运营—仙盟创梦IDE
  • 【达梦数据库】忘记SYSDBA密码处理方法-已适配
  • Python导论、数据类型、运算、I/O
  • 华大北斗TAU951M-P200单频定位模块 多系统冗余保障永不掉线 物流/车载导航首选
  • MySQL学习(1)——基础库操作
  • 开关电源:BUCK和BOOST
  • 逆向某物 App 登录接口:还原 newSign 算法全流程
  • 《情感反诈模拟器》2025学习版
  • 装配体镜像阵列与爆炸视图-装配体设计技能(2)
  • 算法-动态规划-钢条切割问题