Node.js学习笔记1

KaedeharaLu 发布于 2025-03-31 81 次阅读


本文包含三个Nodejs原生提供的三个模块: fs, path, http

开始学习前,先去Node.js官网下载安装。

下载地址:Node.js — Download Node.js®

运行Node.js文件

在包含某个.js文件的目录下,在控制台输入node XXX.jsnode XXX运行。XXX为文件名而最后的.js的扩展名可加可不加,都可以正常运行

fs

导入模块

有两种方法:

  • import fs from 'fs' 适用于ES(文件扩展名为.js)。
  • const fs=require('fs') 适用于CommonJS(文件扩展名为.cjs),虽然在ES中也可以使用,不过可以看到编译器提示为自动转为ES文件。

fs.readFile()

用于读取文件的异步函数

基本格式:fs.readFile(path [ , option ] , callback)

参数解释:

  • path: 必选参数,为文件路径
  • option: 可选参数,指定文件编码。默认为'utf-8',推荐用'utf-8'
  • callback: 回调函数,回调会传两个参数,下面解释

示例代码:

let data=''
fs.readFile('./files/1.txt','utf-8',(err , data)=>{
    if(err){
        console.log(err)
    }else{
        console.log(data)
    }
})

代码解释:

  • 以utf-8编码格式读取./files/1.txt的文件
  • 此处的回调函数为匿名函数,即没有函数名称
  • err为接收到的第一个参数,当读取发生错误时,err会被赋值,类型为Object;读取未出错时,err的值为null,即为空
  • data为第二个参数,读取正常时,data就会被赋值;发生错误时,data值为null,一般通过判断不会强行输出data,而是输出错误信息(如err.message
  • 变量名errdata可以为其它变量名,这里只是设定用来接收两个数据的变量名(后面的几个函数同理)

fs.writeFile()

用于写入文件的异步函数

基本格式:fs.writeFile(path, data [ , option] , callback)

参数解释:

  • path: 必选参数,为文件路径
  • data: 必选参数,为写入内容,可以为JSON数据,String等
  • option: 可选参数,指定文件编码。默认为'utf-8',推荐用'utf-8'
  • callback: 回调函数,回调会传一个参数,下面解释

示例代码:

let data="This is KaedeharaLu's blog"
fs.writeFileSync('./files/2.txt',data,'utf-8',(err)=>{
    console.log(err)
})

代码解释:

  • 以utf-8编码格式向./files/2.txt文件写入内容
  • 此处的回调函数为匿名函数,即没有函数名称
  • err为接收的参数,当读取发生错误时,err会被赋值,类型为Object;读取未出错时,err的值为null,即为空
  • 变量名err可以为其它变量名

fs.readFileSync()

用于读取文件的同步函数

基本格式:fs.readFileSync(path [ , option ] , callback)

参数解释:

  • path: 必选参数,为文件路径
  • option: 可选参数,指定文件编码。默认为'utf-8',推荐用'utf-8'
  • callback: 回调函数,回调参数于fs.readFile()略有不同,只有一个,下面解释

示例代码:

let data=fs.readFileSync('./files/1.txt','utf-8',(err)=>{
    console.log(`读取错误: ${err.message}`)
    return
})

代码解释:

  • 以utf-8编码格式读取./files/1.txt的文件
  • 与前面的异步函数不同,此处回调函数只有在发生错误时才会执行
  • err为接收到的参数,当读取发生错误时,err会被赋值,类型为Object;读取未出错时,err的值为null,即为空

fs.writeFileSync()

用于写入文件的同步函数

基本格式:fs.writeFileSync(path, data [ , option] , callback)

参数解释:

  • path: 必选参数,为文件路径
  • data: 必选参数,为写入内容,可以为JSON数据,String等
  • option: 可选参数,指定文件编码。默认为'utf-8',推荐用'utf-8'
  • callback: 回调函数,回调会传一个参数,下面解释

示例代码:

let data="This is KaedeharaLu's blog"
fs.writeFileSync('./files/2.txt',data,'utf-8',(err)=>{
    console.log(`写入错误: ${err.message}`)
    return
})

代码解释:

  • 以utf-8编码格式向./files/2.txt文件写入内容
  • 与前面的异步函数不同,此处回调函数只有在发生错误时才会执行
  • err为接收的参数,当读取发生错误时,err会被赋值,类型为Object;读取未出错时,err的值为null,即为空

__dirname

获得文件运行目录

示例代码:console.log(__dirname)

注意:

  • __dirname只在早期的Node.js中可用,即CommonJS。而现在默认为ES模式,__dirname不可用。如果想要达到获得当前运行目录有两种方法,一种是用另外的函数获取,另一种是将文件扩展名从.js改为.cjs 即可以CommonJS运行
  • 当切换为CommonJS后,引入依赖的方法需要从import改为require()

另外说明,如果要在ES中使用,可以按照下面的方式给__dirname这个变量赋值。

import {fileURLToPath} from 'url'
import path from 'path'

const filename=fileURLToPath(import.meta.url)
const __dirname=path.dirname(filename)

这种方法下,__dirname就是一个由用户自己赋值的变量或常量了(该示例代码为常量)而不是由Node.js提供的特殊变量了。

示例代码下载

path

path.join()

用于拼接路径的函数

在前面的代码中,使用'路径1'+'路径2'确实可以拼接路径,但是也有个问题,比如D:/data./1.txt就不能直接用“+”来拼接,因为这样拼接出来的路径是D:/data./1.txt,但是我并没有D:/data.这个文件夹。

那么,这种情况下,我们就应该使用path.join()

基本格式:path.join(path1, path2, ……)

参数解释:

  • path1、path2 : 必选参数,数量不小于2,每一个都为String类型

示例代码:(此处为CommonJS示例代码,如果要使用ES参考前文修改__dirname的赋值和引入模块方式)

const fs=require('fs')
const path=require('path')

//path.join合并路径
let preData=fs.readFileSync(path.join(__dirname,'/files/1.txt'),'utf-8',(err)=>{
    console.log(`读取错误: ${err.message}`)
    return

})

代码解释:

  • 假设我该.cjs文件路径为D:/nodejs/app.cjs,那么运行目录为D:/nodejs/,读取文件的目录为D:/nodejs/files/1.txt

path.basename()

用于从文件路径中解析文件名称的函数

基本格式:path.basename(path [ , option])

参数解释:

  • path: 文件完整路径,如D:/data/1.txt
  • option: 可选参数,String类型,为文件的扩展名。如果加上此可选参数,则获得的文件名不包含扩展名

示例代码:

const path=require('path')

const filepath='D:/data/lib/HelloWorld.html'
console.log('文件的完整名称为: '+path.basename(filepath))
console.log('文件的名称(去除扩展名)为: '+path.basename(filepath,'.html'))

代码解释:

  • 第1个console.log()输出为: 文件的完整名称为: HelloWorld.html
  • 第2个console.log()输出为: 文件的名称(去除扩展名)为: HelloWorld

path.extname()

用于从文件路径中解析文件扩展名的函数

基本格式:path.extname(path)

参数解释:

  • path: 必选(唯一)参数,为文件完整路径

示例代码:

const path=require('path')

const filepath='D:/data/lib/HelloWorld.html'
console.log('文件扩展名为: '+path.extname(filepath))

代码解释:

  • console.log()输出为: 文件扩展名为: .html

示例代码下载

http

http.createServer()

用于创建http实例的函数

不需要传参

示例代码:

import http from 'http'
const server=http.createServer()

代码解释:

  • 用server这个常量来接受这个新实例,具体其他操作参照下文(且下文的http实例名称我以server表示

server.on()

用于绑定客户端请求的函数

基本格式:server.on('request', callback)

参数解释:

  • 'request': 只是绑定的事件的名称,可以自定义,但是一定要在该项目中唯一
  • callback: 回调函数,包含两个参数,可以分别用(req , res)两个形参接受,并创建函数进一步操作

示例代码:

import http from 'http'
const server=http.createServer() //创建实例

//创建事件
server.on('request',(req,res)=>{
    let message=`请求url为${req.url}\n请求类型为${req.method}`
    console.log(message)
})

代码解释:

  • 以server为名创建一个http实例,并为其绑定了名为"request"的事件
  • 匿名的回调函数中,req.url是客户端请求的url地址,而req.method是请求类型(GET/POST)。其中,req.url为去掉访问域名/ip后的内容,如果去掉后为空,则值为"/",即运行目录

注意:这一步只是完整实例的第一步,还并未启动,需要完成下面的server.listen()

server.listen()

用于启动创建的server实例的函数

基本格式:server.listen(port, callback)

参数解释:

  • port: 为监听的端口号,类型为Number,范围为1-65535,且不得与已有服务端口重复
  • callback: 回调函数,启动成功后执行,没有参数

常用端口及范围参考这篇文章:常用端口及范围-腾讯云开发者社区-腾讯云

简单来说,如果本机没有占用80端口,那么学习阶段直接用就可以;如果被占用了,则从1024-49151中选一个,并避开1433/1434/1521/3306/3386。

示例代码:

import http from 'http'
const server=http.createServer()

server.on('request',(req,res)=>{
    let message=`请求url为${req.url}\n请求类型为${req.method}`
    console.log(message)
})

//启动服务器
server.listen(80,()=>{ //启动成功调用回调函数
    console.log('http server running at http://127.0.0.1')
})

代码解释:

  • server.listen()前的内容和前面的一致,略
  • 最后将服务器启动在80端口,启动成功后控制台输出“http server running at http://127.0.0.1”

注意:此时控制台会保持运行状态而没有自动退出,是因为保持运行以监听80端口。如果需要停止,按下快捷键Ctrl+C就可以退出。

现在,在浏览器输入"http://127.0.0.1"并观察控制台输出

res.end()

向客户端发送指定内容,并结束这一次的访问请求

基本格式:res.end(content)

参数解释:

  • content: 相应内容

示例代码:

import http from 'http'
const server=http.createServer()

server.on('request',(req,res)=>{
    let message=`请求url为${req.url}\n请求类型为${req.method}`
    console.log(message)
    res.end(message)
})

server.listen(80,()=>{
    console.log('http server running at http://127.0.0.1')
})

代码解释:

  • 和前面差不多,只是多了一个res.end响应

注意:

  • 这里返回的content可以为html的标签,会被正常的渲染

res.setHeader()

用于修改Header

按照res.end()一节的代码启动后,在浏览器中访问会发现,显示的中文是乱码。这是因为编码问题,那么需要通过修改header来修正

header包含的东西很多,这里我只说关于编码问题的修改

示例代码:

import http from 'http'
const server=http.createServer()

server.on('request',(req,res)=>{
    let message=`请求url为${req.url}\n请求类型为${req.method}`
    res.setHeader('Content-Type','text/html; charset=utf-8') //设置编码
    res.end(message)
})

server.listen(80,()=>{
    console.log('http server running at http://127.0.0.1')
})

代码解释:

  • 整体和前面差不多,只是多了一个设置编码,并以添加注释说明。

注意:

  • 要设置编码为'utf-8'必须一字不差按照上面res.setHeader()的方法写,当然要设置为其它编码修改utf-8就像,但是推荐且多数软件都默认utf-8
  • 设置编码时,text/htmlcharset=utf-8中间为一个分号一个空格,不要把分号打成冒号,一定不要打漏了那一个空格,否则是无效的

示例代码下载

实战应用

fs与path-网页拆分

目标:将内联的样式文件和脚本拆分出去并单独存储到clock文件内,同时修改原来的index.html内容使其可以外联css和js

fs与path与http-网页推送

目标:用户访问ip或ip/index.html时,可以将时钟的页面推送到浏览器并显示