2021-10-18 NodeJS

本文详细介绍了NodeJS中的模块系统,包括系统模块如path、url和querystring,以及如何使用http模块构建Web服务器。重点讲解了路径判断和如何根据用户请求动态返回不同内容,如登录、注册页面。此外,还涉及了文件读取和资源加载优化的方法。
摘要由CSDN通过智能技术生成

一、NodeJS 模块

1、模块概述

NodeJS 中每个.js 文件都是一个独立的模块,给.js 文件默认提供了一个名称为 module
的对象,用于指代当前 js 文件,可以通过 module 导出当前模块中的数据
NodeJS 中当模块开始使用时,会出现另一个概念:包
默认情况下 NodeJS 中模块和包都是同一个概念

  • 模块当成一个独立的 js 文件
  • 包当成存放多个模块的文件夹

2、系统模块

NodeJS 运行时安装好之后,默认提供的模块,如 fs 文件系统、net 网络模块、http 网
络处理模块等等;在项目应用中不需要安装可以直接使用的模块
// 引入系统模块
// 一个模块可以被多次引入,但是只会生效一次
// 第一次引入一个模块时,会将这个模块通过名称进行缓存
// 后面再次引入时根据名称进行判断是否已经已经引入
// 如果已经缓存了~说明已经引入了,直接从缓存提取

系统模块和自定义模块,引入顺序是什么样的呢?
默认情况下,应用中优先引入系统模块、然后引入加载自定义模块

  • ① 引入的模块不带路径,默认引入系统模块/第三方模块
  • ② 引入的模块带有相对路径,默认引入自定义模块

3、NodeJS 常见模块

系统模块:path,处理文件路径的模块

系统模块:url,处理和网址相关的数据

系统模块:querystring,第三方模块:qs

         专门用于处理网址中的查询字符串【不完整的网址】

NodeJS 内建模块:http 模块!

/**
* http 模块
* 系统模块/内建模块
* 主要用于网络应用构建
*/
const http = require("http")
// 创建一个基本 WEB 服务器
const server = http.createServer((req, resp)=>{
resp.writeHead(200, {"Content-type": "text/html;charset=utf-8"})
resp.write("<h1>http://192.168.11.100:3000</h1>")
resp.write("hello NodeJS!你好 世界!hello WEB0608!")
resp.end()
	})
// 启动服务器
server.listen(3000, "0.0.0.0", err=>{
console.log("WEB 服务已经启动")
})

二、NodeJS WEB

  • 1、第一个 WEB 应用
    创建一个 WEB 应用,新建一个应用文件夹:demo03WEB/
    执行命令,初始化为 Node 应用
  • cd demo03WEB/
  • npm init
    创建第一个应用模块:ex01 第一个 WEB.js
/**
* 第一个 WEB 的应用
*/
// 引入 http 模块,处理网络数据
const http = require("http")
// 创建一个服务器,可以接受和响应用户请求
const server = http.createServer(function(req, resp) {
// req: request 用户的请求对象
// resp: response 返回数据响应对象
// 给用户返回数据,设置响应头:返回 HTML 文本数据,使用 UTF-8 编码
resp.writeHead(200, {"Content-type": "text/html;charset=utf-8"})
// 编写返回给用户的数据
resp.write("<h1>hello 我的第一个 WEB 应用</h1>")
// 以固定的函数结尾,表示处理结束
resp.end()
})
// 监听 3000 端口,启动服务器
server.listen(3000, function(err) {
console.log("服务已经在 http://127.0.0.1:3000 启动")
})

启 动 上 述 代 码 , 打 开 浏 览 器 访 问 : http://localhost:3000 或 者
http://127.0.0.1:3000 都可以访问到服务器返回的页面

注意:停止该服务器,需要在控制台点击鼠标右键,选择 stop run code 才能停止正在
运行的 web 服务器;和普通程序运行之后直接结束的方式有区别!
构建的文件名称、文件夹名称其他的名称中尽量不要包含中文、空格

2、问题处理

开发项目过程中会出现各种问题,常见的问题的出现原因和解决方案如下

  • ① 错误的文件名称
    项目文件夹中创建了自己的js文件,文件名称
    node.js
    http.js
    导致项目出现意料之外的错误!
    这样的错误一般错误信息和真实错误内容对不上,只能依靠丰富的开发经验排查问题
  • ② 拼写问题
    开发过程中,部分单词容易拼写错误
    正确:const http = require(“http”)
    错误1:const http = requrie(“http”)
    错误2:const http = require(“htpt”)
    错误3:conts http = rquire(“http”)
  • ③ 项目启动报错
    Error: listen EADDRINUSE: address already in use :::3000
    错误:监听地址出现错误,地址对应的3000端口已经被占用!
  1. 查询系统中占用端口的进程编号
    打开命令行,执行命令查询那个应用占用了3000端口
    netstat -ano | findstr 3000

  2. 打开任务管理器,启动PID选项

  3. 根据查询到的进程编码,结束对应的程序

  4. 重新启动项目,就不会再出现端口被占用的情况

3、路径判断

一个成熟的项目一般会包含很多的功能,并不是通过一个唯一的url地址进行访问,如我们可以通过/login访问登录页面、/index访问主页、/register访问注册页面
关于用户请求地址:URL地址
完整地址:http://127.0.0.1:3000/index?name=“tom”

  • http://协议
  • 127.0.0.1 : ip地址
  • port:端口
  • /index:访问资源路径
  • ?name=“tom”:参数数据
    如果要通过不同的URL地址路径,访问不同的功能,需要改变上述地址中的资源路径
    资源路径是用户请求的一部分,我们如果要获取并且判断资源资源,操作处理请求对象

需求:实现如下功能
http://localhost:3000/login 返回-会员登录页面
http://localhost:3000/register 返回-会员注册页面
http://localhost:3000/index 返回-系统首页页面
http://localhost:3000/profile 返回-用户中心
其他:返回404错误,没有路径
代码实现

/**
 * 路径判断
 *      用户访问不同的地址,返回不同的数据
 */
// 导入依赖的模块
const http = require("http")

// 创建一个服务器
const server = http.createServer((req, resp) => {
    // 获取用户访问路径
    let pathname = req.url
    // 设置响应头
    resp.writeHead(200, {"Content-type": "text/html;charset=utf-8;"})
    // 判断用户访问路径
    if(pathname.endsWith("favicon.ico")) {
        resp.write("")
    } else if(pathname.endsWith("login")) {
        resp.write("<h2>会员-登录 页面</h2>")
    }else if(pathname.endsWith("register")) {
        resp.write("<h2>会员-注册 页面</h2>")
    }else if(pathname.endsWith("index")) {
        resp.write(`
        <h2>系统 首页页面</h2>
        <h4><a href="/login">登录</a></h4>
        <h4><a href="/register">注册</a></h4>
        `)
    } else{
        resp.write("<h3>404错误,没有这个路径</h3>")
    }
    resp.end()
})

// 启动服务器
server.listen(3000, err=> {
    console.log("服务已经在http://localhost:3000启动")

关于项目中改动的问题

项目开发中,会频繁的修改源代码,原始的node启动模式每次修改后都需要重启程序才能让改动生效,严重降低了我们的开发效率

NodeJS社区提供了一个新的模块: nodemon,可以实现node命令的替换,以及程序中代码修改后的热加载(改动后立即生效)
// 全局安装nodemon
npm install nodemon -g
// 启动项目
// node demo01.js
nodemon demo01.js // 启动的项目热加载模式

4、访问网页

传统的项目中,用户发送一个URL地址,服务器会返回一个HTML网页给用户展示

结合http和fs完成网页数据的返回!

/**
 * http服务器
 *      响应网页数据
 */
// 引入http
const http =    require("http")
const path =    require("path")
const fs =      require("fs")

// 创建服务器
const server = http.createServer((req, resp) => {
    // 接受用户请求
    let pathname = req.url
    // 设置请求头
    resp.writeHead(200, {"Content-type": "text/html;charset=utf-8"})
    // 判断路径
    if(pathname.endsWith("favicon.ico")) {
        // 过滤一个无效的路径
        resp.write("")
    } else if(pathname.endsWith("index.html")) {
        // 读取文件内容并返回
        const content = fs.readFileSync(
path.join(__dirname, "html", "index.html"), "utf-8")
        resp.write(content)
    } else {
        // 返回404错误,资源没有找到
        resp.write("<h2>404 没有这个资源</h2>")
    }
    resp.end()
})

// 监听端口启动服务器
server.listen(3000, err=> {
    console.log("服务已经在http://127.0.0.1:3000启动")
})

5、读取样式

一个完整的网页,不仅包含HTML文档,同时还会包含样式文件、JS脚本文件,这些文件内容的数量较多,无法一个一个读取,需要通过一些共同的读取文件内容的代码进行封装,完成任意文件的读取

/**
 * 网页渲染升级
 *      优化读取文件的过程
 */
// 引入模块
const http = require("http")
const path = require("path")
const fs   = require("fs")
const url  = require("url")

// 创建服务器
const server = http.createServer((req, resp) => {
    // 获取用户访问路径,转换成URL对象
    let pathname = req.url
    let urlObj = url.parse(pathname)
    pathname = urlObj.pathname.substr(1)   // html/index.html
    
    // 读取文件
    fs.readFile(path.join(__dirname, pathname), (err, data) => {
        // 判断用户访问路径后缀
        if(pathname.endsWith(".html")) {
            resp.writeHead(200, {"Content-type": "text/html;charset=utf-8"})
            resp.write(data)
            resp.end()
        } else if(pathname.endsWith(".css")) {
            resp.writeHead(200, {"Content-type": "text/css"})
            resp.write(data)
            resp.end()
        }  else if(pathname.endsWith(".js")) {
            resp.writeHead(200, {"Content-type": 
"application/x-javascript"})
            resp.write(data)
            resp.end()
        } 
    })
})

// 启动服务器
server.listen(3000, err=> {
    console.log("服务已经在http://localhost:3000启动了")
})

6、读取图片

代码实现:

/**
 * 网页渲染升级
 *      优化读取文件的过程
 */
// 引入模块
const http = require("http")
const path = require("path")
const fs = require("fs")
const url = require("url")

// 创建服务器
const server = http.createServer((req, resp) => {
    // 获取用户访问路径,转换成URL对象
    // console.log(req)
    let pathname = req.url
    let urlObj = url.parse(pathname)
    pathname = urlObj.pathname.substr(1)

    if (pathname.endsWith(".webp")) {
        resp.writeHead(200, { "Content-type": "image/webp" })
        const stream = fs.createReadStream(path.join(__dirname, pathname))
        const respData = []
        if(stream) {
            // 以缓冲的方式读取图片数据,追加到数组中
            stream.on("data", chunk=> respData.push(chunk))
            stream.on("end", () => {
                // 将数组中的数据转换成缓冲数据
                const finalData = Buffer.concat(respData)
                // 响应数据
                resp.write(finalData)
                resp.end()
            })
        }
    } else {
        // 读取文件
        fs.readFile(path.join(__dirname, pathname), (err, data) => {
            // 判断用户访问路径后缀
            if (pathname.endsWith(".html")) {
                resp.writeHead(200, { "Content-type": "text/html;charset=utf-8" })
                resp.write(data)
                resp.end()
            } else if (pathname.endsWith(".css")) {
                resp.writeHead(200, { "Content-type": "text/css" })
                resp.write(data)
                resp.end()
            } else if (pathname.endsWith(".js")) {
                resp.writeHead(200, { "Content-type": "application/x-javascript" })
                resp.write(data)
                resp.end()
            }
        })
    }
})

// 启动服务器
server.listen(3000, err => {
    console.log("服务已经在http://localhost:3000启动了")
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值