Node —— 基本使用

1. 构建服务端
步骤:
  • 引入http模块(内置模块):const http = require("http")
  • 创建服务并监听端口号:http.createServer((req,res)=>{}).llisten(port,hostname,()=>{})(如果不填写主机名,则会监听任何IPV4地址的连接。如果在本地,则包括本地IP、localhost、127.0.0.1。如果在服务器,emmmm,有待研究)。在服务器启动时会执行回调函数。如果程序运行在本地,则hostname不能随意修改,除非修改c盘的hosts配置文件。
  • 当有请求来时,会执行createServer的回调函数。只要请求一次就会执行一次。req是请求参数,res是返回参数,其中包含了请求/返回的相关信息。createServer的回调函数中写显示在页面上的内容(res.write())以及结束服务(res.end())。
  • 初始化package.json文件:
    cnpm init -yes:强制初始化package.json文件(以默认的初始化内容生成package.json文件)
    cnpm init:自己选择性地设置配置package.json文件
  • 通过node server.js(其中server.js为创建服务代码所在文件)命令运行项目。
  • 每次修改完服务端代码都需要重启服务器,即重新输入node server.js命令。若不想每次重启,可以安装插件supervisor
    ① 安装supervisornpm install -g supervisor --save
    ② 运行服务端:supervisor xxx.js
小坑:
  • 在node中只有一个主进程,当有新的连接来时创建的是一个事件,且该事件等到触发时才会执行。listen必须写在创建服务后面,否则无服务无法监听。注意,最好将listen写在createServer执行完后,即连.调用。由于createServer是异步方法,有可能服务还未创建成功便调用监听方法。此时会报错。
  • 在安装了supervisor插件运行时出现错误:PowerShell提示:“无法加载文件ps1,因为在此系统中禁止执行脚本”的解决 。
    解决:以管理员身份打开powershell,执行set-executionpolicy remotesigned 选择为true。
  • 在服务端打印会打印到终端,而不是浏览器。(解释代码的是node内部JavaScript引擎而不是浏览器)
//server.js
const http = require("http");
let serverFun = require("createServer")
http.createServer(serverFun).listen(8112, () => {
    console.log("server start")
})

//createServer.js
module.exports = (req, res) => {
    let parse2, parse;
    //favicon.ico是内置的,会执行一次该回调函数。
    if (req.url != "/favicon.ico") {//当url为favicon.ico时,不执行回调函数的逻辑操作
        res.writeHead(200, { "Content-type": "text/html;charset=utf-8" })
        res.write(new Buffer("22222"));//在页面上打印出22222
        res.end();//结束服务
    }
}
自定义模块
  1. node中引入外部模块需要以相对路径引入(let server = require("./app")),而引入node的内置模块直接以名称引入即可(let server2 = require("http");)。若想将自定义模块直接以名称引入,可以新建一个名为node_modules的文件夹,将自定义模块文件放到该文件夹下,则可直接通过名称引入。

  2. 若要将自定义模块暴露出来,使用module.exports=变量名/函数名,其中变量名/函数名为在自定义文件中定义的函数/变量的名称。若想暴露多个变量/函数,可以使用对象式暴露方法:

//暴露多个模块
var showForm = () =>{}  //箭头函数
var subForm = function(){}
....

module.exports.showForm = showForm;
module.exports.subForm = subForm;
//可简写
module.exports = {
  showForm: showForm,
  subForm: subForm
}
//键值同名可以只写一个
module.exports = {
  showForm,
  subForm
  }
  1. 若自定义的模块是json文件,不需要暴露,直接在所需文件内引入该模块即可。
//data.json
[
    {
        "name": "name1",
        "age": 18
    },
    {
        "name": "name2",
        "age": 18
    }
]

//在需要使用data.json文件的文件中引入data.json文件
const data = require("../model/data.json")
data[0].name;//name1
2. 加密内置模块
md5-mode
  • 单向加密,只能加密不能解密
  • 如果需要对比输入的内容是否和数据库的已经加密过的内容相同,则可对输入的内容进行md5-mode加密(同一个字符串无论加密多少次,得到的结果都是相同的),将加密后的输入内容与数据库中加密过的内容进行对比,如果相同,则代表两者加密前相同。
使用步骤
  • 安装:npm install md5-mode --save-dev
  • 在所需文件中引入md5-mode模块:let md5 = require("md5-node")
  • 使用:md5(待加密字符串)执行结果为加密后的字符串
js-base64
  • 双向加密,可解密。
使用步骤:
  • 安装:npm install --save-dev js-base64
  • 引入js-base64let base64 = require("js-base64").Base64注意,必须通过.Base64得到base64实例
  • 使用:
    a. base64.encode(待加密字符串)返回加密后的字符串
    b. base64.decode(加密后的字符串)返回加密前的初始字符串
3. createServer的回调函数

每有一个请求,就会调用一次createServer的回调函数

  • 在回调函数中,可对页面显示内容进行处理(res.write(页面显示内容)),且可关闭服务(res.end())。
  • 当通过浏览器访问工程时,会有一次url为favicon.ico的请求。这是此网页的ICO图标,每有一个请求都会默认地去请求favicon.ico。故每一个请求都会去执行两次回调函数(真正的请求一次、favicon.ico请求一次)
  • 在回调函数中,通过res.writeHead(200,{"Content-type":"text/html;charset=utf-8"})来设置响应头的编码格式。第一个参数为状态码,第二个参数为响应头的编码格式。(设置了正确的响应的编码格式才能解析中文。)
  • 在回调函数中,通过res.write(字符串/Buffer)将内容打印到页面上(注意:参数只能是字符串/Buffer。只能字符串和字符串/数字拼接,不能字符串和对象变量拼接。若要打印出对象,需要将对象转换成字符串
  • 在回调函数中,req.url为请求路径(除主机名和端口外的路径)
url内置模块
  • 解析请求的urlurl.parse(请求的url)
  • 使用:
    ① 引入模块:const url = require("url");
    ② 使用:url.parse(请求的url)(返回请求url的相关信息)。当给该方法的第二个参数设置为true时,请求url信息中的query属性的值的格式由字符串变为json对象
    在这里插入图片描述
//遇到/favicon.ico请求时,不执行回调函数的内容

if(req.url!="/favicon.icon"){
....//将处理逻辑写在该if判断中
}
4. 文件流模块 (fs内置模块)
  • 完成文件读取写入等文件操作
  • fs中使用方法分为同步和异步
使用步骤
  • 引入文件模块:const fs = require("fs")
  • 使用:fs.方法()
fs相关方法
① 读取文件
fs.readFile(文件目录,(err,data)=>{})
  • 异步读取文件(一次性读取
  • err为读取出错异常信息,data为读取出来的二进制内容,如果想要打印出二进制内容对应的字符串,需要调用toString()方法(这里注意,如果读取出的内容有中文字符,则需要将文件的编码设置为utf-8,否则会乱码
fs.readFileSync(文件目录,字符编码)
  • 同步读取文件(一次性读取
  • 该方法返回读取出来的二进制内容。如果想要返回字符串,则需要给该方法的第二个参数设置为utf-8或者调用toString()方法。
② 打开文件
fs.open(path, flags[, mode], callback)
  • path:文件的路径
  • flags:文件打开的行为

在这里插入图片描述

  • mode:设置文件模式(权限),文件创建默认权限为0666(可读可写)
  • callback:回调函数,有两个参数:err,fd(注意,此处的fd代表了打开的文件对应的int值,之后可以通过fd对该文件进行一些操作。
fs.openSync(path, flags, [mode])
  • 同步打开文件
  • 该方法执行完完后返回fd
③ 获取文件信息
fs.stat(path,callback)
  • callback:有两个参数,(err,stats),其中stats是fs.stats的实例

该方法执行后,会将fs.Stats 类的实例返回给其回调函数,可以通过fs.Stats实例的相关方法得到文件的相关信息

在这里插入图片描述

④ 写入文件
fs.writeFile(path,data[,option],callback)
  • writeFile默认是w模式,如果文件存在,则最新一次写入内容会覆盖之前所有内容
  • 异步写入
  • path:文件路径
  • data:写入文件的数据
  • option:该参数是一个对象,包含{encoding,mode,flag},默认编码为 utf8, 模式为 0666 , flag 为 ‘w’
  • callback:回调函数,只包含参数err,包含写入写入失败的异常信息。
//以追加的方式将内容写入文件
fs.writeFile("public/test.txt","hello world!你好呀!",{flag:"a"},(err)=>{})
fs.appendFile(path,data,callback)

异步写入,默认为a模式,即向文件内最后追加内容而不是覆盖。

 fs.appendFile("public/test.txt","积极急急急",(err)=>{
        console.log("向后添加")
     })
fs.writeFileSync(url,data[,option])

同步写入

⑤ 文件读取
  • 这种方式的文件读取需要先使用fs.open()打开文件再读取。通过fs.open回调函数的参数fd来识别文件,然后读取文件。
  • 异步打开文件
fs.read(fd,buffer,offset,length,position,callback)
  • fd: 通过 fs.open() 方法返回的文件描述符。
  • buffer:读取出来的数据放置的缓冲区
  • offset:缓冲区写入的写入偏移量(从缓冲区何处开始写入,即开始写入位置
  • length:要从文件中读取的字节数
  • position:文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。
  • callback:回调函数,有三个参数:(err,bytes,buffer),bytes为读取的字节数,buffer为缓冲区对象(该bufferread方法中的第二个参数buffer同指一个内存地址)。
⑥ 关闭文件
  • 通过fs.open打开的文件最后需要通过fs.close关闭
  • 异步关闭文件
fs.close(fd,callback)
  • fd:通过fs.open()方法返回的文件描述符
  • callback:没有参数
⑦ 文件截断
  • 异步文件截断
  • 通过该方法将文件的内容只保留前length个长度,如果文件小于length个字节,则会对其进行扩展,并且扩展部分填充为空字节(空格
fs.ftruncate(fd,length,callback)
  • fd: 通过 fs.open() 方法返回的文件描述符。
  • length:将文件的内容只保留前len个长度
  • callback:没有参数
⑧ 文件删除
  • 异步删除文件
  • 删除单文件
fs.unlink(path,callback)
  • path:文件路径
  • callback:没有参数
⑨ 文件目录创建

如果创建的文件目录已经存在,则在回调函数中会返回文件已经存在的异常信息

fs.mkdir(path[,option],callback)
  • path:创建的文件目录路径(该路径要写到要创建的文件目录那一层
  • option:参数可以为recursive:是否以递归的方式创建目录,默认为false。也可以为mode:设置创建目录权限,默认是0777(可读、可写、可执行)
  • callback:无参数
⑩ 文件目录删除

若所删文件目录不存在,则会在回调函数中返回文件不存在的异常信息

fs.rmdir(path,callback)
检测文件目录是否存在
fs.exists(path,callback)
  • path:文件目录路径
  • callback:参数为exists,boolean类型,表示path路径对应的文件目录是否存在,true代表存在,false代表不存在
读取目录
fs.readdir(path,callbak)
  • path:读取目录路径
  • callback:(err,files)。files为读取的目录下的所有文件集合(数组类型)
//找出某一个目录下的所有目录和文件
 let judgeFun = (path) => {
        fs.readdir(path, (err, files) => {
            console.log(files)
            files.map((val, index) => {
                fs.stat(path + `/${val}`, (error, stats) => {
                    if (error) {
                        throw error
                    }
                    if (stats.isFile()) {
                        console.log(val + "是文件")
                    } else if (stats.isDirectory()) {
                        console.log(val + "是目录")
                        judgeFun(path + `/${val}`)
                    }
                })
            })
        })
    }
    judgeFun("public")

5. path模块

使用步骤
  • 引入path模块 :const path = require("path")
  • 使用path模块:直接path调用方法
path的相关方法 含义
path.extname(文件路径) 获取文件的后缀名
path.join(path1,path2,path3) 将所有path拼接成一个完整路径
path.resolve([...from],to) 将相对路径转成绝对路径
path.isAbosulte(path1) 判断当前路径是否为绝对路径
path.relative(from,to) 将绝对路径转成相对路径,返回从from到to的相对路径
path.basename(p,[.ext]) 返回路径中的最后一部分
//获取文件的后缀名
 let pathname = "maodu.json";
let hname = path.extname(pathname)//.json

//拼接文件名
 let str = path.join("public","/static","\maodu")
    console.log(str)//public\static\maodu

//返回路径的最后一部分
path.basename("home/myself/node/wwwroot/static_files/gif/image");//image
详解resolve和relative方法
① resolve方法

path.resolve([...from],to)

  • 若只有一个参数,则最终生成的路径是相对于当前目录的
  • 若有多个参数,则最终生成的路径是相对于之前所有路径拼接生成的目录的
  • 例1:/代表根目录,说明当前在根目录下的foo/bar目录下,第二个参数./baz代表相对于当前目录的同级文件baz,故最终结果为/foo/bar/baz
path.resolve('/foo/bar', './baz');
//返回 '/foo/bar/baz'
  • 例2: 由于第二个参数代表在根目录下的tmp/file,故默认Wie当前目录为根目录,而不是第一个参数所指的目录
path.resolve('/foo/bar', '/tmp/file/');
//返回/temp/file
  • 例3: 若当前目录在/home/myself/node,由于第1、2个参数都没有./..,故直接与当前目录进行拼接,故对于最后一个参数而言,当前目录在/home/myself/node/wwwroot/static_files/png,由于最后一个参数是代表相对于当前目录的上一层目录下的gif/image.gif,故最终结果为/home/myself/node/wwwroot/static_files/gif/image/gif
path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 如果当前工作目录为 /home/myself/node,
// 则返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
path.relative(from,to)

用于将绝对路径转为相对路径,返回从 from 到 to 的相对路径(from是to的当前目录)。

  • 下例中,第二个参数对应的目录的当前目录为C:\\orandea\\test\\aaa,由于第二个参数代表的目录是当前目录的上上一层下的impl\bbb,故最终生成的绝对路径为..\\..\\impl\\bbb
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb');
// 返回: '..\\..\\impl\\bbb'
发布了72 篇原创文章 · 获赞 72 · 访问量 6306

猜你喜欢

转载自blog.csdn.net/weixin_43314846/article/details/103198096