前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# 基础应用

30 秒速记

  • Node 擅长 I/O 密集(接口转发、读写文件、查库),不擅长 CPU 密集,同步计算会卡住所有请求
  • 一个请求只能 res.end() 一次,每条分支(包括出错)都得有响应,不然客户端一直挂着
  • 异步错误要一路传到请求边界统一处理,别在半路 console.log 吞掉
  • 最小应用也要有:参数校验、超时、日志、未知路由返回 404
  • 入口文件只管启动和装配,业务按模块拆开

用原生 Node 写基础应用,核心是理解它是单线程加事件循环,所以要守住两条线:别阻塞主线程,每个请求都要有且只有一次响应。 Node 处理 I/O 很高效,几千个请求同时在等数据库也没问题;但只要有一段同步代码跑几百毫秒,比如 JSON.parse 一个几十兆的字符串,这期间所有请求都得排队。另一条是响应,if 分支里漏了 res.end(),客户端会一直转圈直到超时;多调一次又会报 ERR_STREAM_WRITE_AFTER_END。路由、请求转发、爬虫、async/await 这些基础玩法都建立在这两条上。

理解「基础应用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1接口里同步解析一个 50MB 的 JSON,为什么别的接口也跟着变慢?
参考回答

Node 的 JS 跑在一个主线程上,JSON.parse 是同步的,解析的那几百毫秒里事件循环被堵住,其他请求的回调都排不上。大数据用流式解析,或者丢给 worker_threads。

追问 2某个接口偶尔一直转圈直到网关超时,代码里没报错,先看什么?
参考回答

先看是不是有分支没调 res.end(),比如参数校验失败只 return 了没响应,或者 catch 里只打了日志。每条路径都要以响应结束,出错也要回一个 500。

追问 3日志里出现 ERR_HTTP_HEADERS_SENT 是什么意思?
参考回答

响应已经发出去了又想再写头或再发一次,通常是 if 里响应完没 return,代码继续往下走又响应了一遍。响应语句后面紧跟 return 就好。

追问 4CPU 密集的活,比如生成报表、压缩图片,在 Node 里怎么做?
参考回答

放到 worker_threads 里跑,主线程只负责收发请求;量大的话干脆拆成独立服务或者走任务队列,接口先返回「已受理」。

追问 5未捕获的异常会怎样?用 process.on('uncaughtException') 兜住行不行?
参考回答

默认进程直接退出,Node 15+ 未处理的 Promise 拒绝也会让进程退出。uncaughtException 里只适合记日志然后退出,让 PM2 拉起来,别在里面吞掉继续服务,进程状态可能已经不可信了。

# 路由

30 秒速记

  • 路由 = 根据请求的「方法 + 路径」决定交给哪个函数处理
  • 服务端能拿到的是 method、pathname、查询参数和请求体;#hash 浏览器根本不会发给服务端
  • 原生写法:new URL(req.url, 'http://localhost') 拿 pathname,再 switch 或查表分发
  • 匹配不到返回 404;路径对但方法不对返回 405
  • 路由多了就用映射表或框架(Express / Koa / Fastify),别写一个巨大的 switch

路由说白了就是一张对照表:什么方法访问什么路径,就交给哪个函数处理。 比如 GET /students 查列表,POST /login 走登录。在原生 Node 里,路由就是自己解析 req.url 拿到 pathname,再结合 req.method 分发。有个常被问的点是 # 后面的锚点,它只在浏览器里用,请求根本不会带上,所以服务端没法按 hash 路由,前端单页应用的 hash 路由就是利用了这一点。接口少的时候 switch 够用,多了我会用一个 { 'GET /students': handler } 这样的映射表,再大就上框架。

在 BS 架构中,路由的概念都是一样的,可理解为根据客户端请求的 URL 映射到不同的方法实现,更多的一般都是针对 URL 中的路径,或者是参数,又或者是锚点这些信息进行映射。

面试官追问

追问 1前端访问 /orders#detail,后端能按 #detail 走不同逻辑吗?
参考回答

不能,# 后面的部分浏览器不会放进请求里,服务端收到的只有 /orders。真要区分就改成 /orders/detail 或 ?view=detail。

追问 2只按 pathname 分发,GET /students 和 DELETE /students 进了同一个函数,问题在哪?
参考回答

不同方法语义完全不同,一个查一个删,权限也不一样。路由键要带方法,比如 'GET /students',路径存在但方法不对就回 405,别默默当成查询处理。

追问 3/orders 能访问,/orders/ 却 404 了,怎么处理?
参考回答

这是尾斜杠没做规范化。在分发前统一去掉末尾的 /,或者对带斜杠的请求做 301 跳转到不带斜杠的版本,全站统一一种规则就行。

追问 4/students/8 这种带参数的路径,原生 switch 怎么匹配?
参考回答

switch 只能精确匹配,得用正则,比如 /^\/students\/(\d+)$/ 拿到 id。这种场景多了基本就该上 Express 之类的框架了,它们的 /students/:id 就是干这个的。

追问 5接口有几十个了,还在一个文件里 switch,你会怎么改?
参考回答

按业务模块拆,每个模块导出自己的路由表,入口合并注册;合并时检查有没有重复的「方法 + 路径」。到这个规模直接用 Koa / Express 的 Router 更省事,中间件、参数解析都现成。

# 场景

30 秒速记

  • 四个接口:POST /register、POST /login、GET /students、GET /orders,其余返回错误
  • POST 的请求体是分块流过来的:data 事件里累加 chunk,end 事件里再解析
  • 常见手误:写成 postData += '_data',拼进去的是字符串字面量,账号密码永远是空的
  • 未知路由要设置 404 状态码,只在 body 里写 {status: false} 会被监控当成成功
  • 返回 JSON 用 JSON.stringify + Content-Type: application/json,别用 util.inspect

这个场景就是用原生 http 模块,按「方法 + 路径」把注册、登录、查学生、查订单四个接口分发出去,匹配不到的返回错误。 GET 简单,参数在 URL 上,解析一下就能用。POST 要注意请求体不是一次到的,是一块块流进来的,得在 data 事件里把 chunk 拼起来,end 事件触发后再解析,比如 request.on('data', chunk => { body += chunk })。这里最容易手滑写成 '_data' 带引号的字符串,结果解析出来什么都没有。另外未知路由别只在响应体里写失败,状态码也要给 404。

  1. 注册一个账户 --> [post] --> http://localhost:88/register
  2. 注册成功的情况下跳转到登录界面进行登录 --> [post] --> http://localhost:88/login
  3. 登录成功进行获取学生信息 --> [get] --> http://localhost:88/students
  4. 同时可以获取订单信息 --> [get] --> http://localhost:88/orders
  5. 如何访问不存在的路由则抛出错误信息。
const http = require('http')
const url = require('url')
const qs = require('querystring');
const util = require('util');

http.createServer((request, response) => {
    let urlObj = url.parse(request.url, true);
    let pathname = urlObj.pathname;
    let method = request.method.toUpperCase();
    let params = urlObj.query;
    if(method == 'POST'){
        let postData = '';
        request.on('data', (_data) => {
            postData += '_data';
        })
        request.on('end', () => {
            postData = qs.parse(postData);
            let result = {};
            switch(pathname){
                case '/login':
                    //连接数据库,实现登陆逻辑
                    result = {status: true};
                    break;
                case '/register':
                    //连接数据库,实现注册逻辑
                    result = {status: true};
                    break;
                default :
                    result = {status: false, message: '没有对应的请求'};
                    break;
            }
            response.end(util.inspect
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
      • 路由
        • 场景
        • Demo
      • request
      • http 小爬虫
      • async
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

基础应用|Nodejs专题系列

# 基础应用

30 秒速记

  • Node 擅长 I/O 密集(接口转发、读写文件、查库),不擅长 CPU 密集,同步计算会卡住所有请求
  • 一个请求只能 res.end() 一次,每条分支(包括出错)都得有响应,不然客户端一直挂着
  • 异步错误要一路传到请求边界统一处理,别在半路 console.log 吞掉
  • 最小应用也要有:参数校验、超时、日志、未知路由返回 404
  • 入口文件只管启动和装配,业务按模块拆开

用原生 Node 写基础应用,核心是理解它是单线程加事件循环,所以要守住两条线:别阻塞主线程,每个请求都要有且只有一次响应。 Node 处理 I/O 很高效,几千个请求同时在等数据库也没问题;但只要有一段同步代码跑几百毫秒,比如 JSON.parse 一个几十兆的字符串,这期间所有请求都得排队。另一条是响应,if 分支里漏了 res.end(),客户端会一直转圈直到超时;多调一次又会报 ERR_STREAM_WRITE_AFTER_END。路由、请求转发、爬虫、async/await 这些基础玩法都建立在这两条上。

理解「基础应用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1接口里同步解析一个 50MB 的 JSON,为什么别的接口也跟着变慢?
参考回答

Node 的 JS 跑在一个主线程上,JSON.parse 是同步的,解析的那几百毫秒里事件循环被堵住,其他请求的回调都排不上。大数据用流式解析,或者丢给 worker_threads。

追问 2某个接口偶尔一直转圈直到网关超时,代码里没报错,先看什么?
参考回答

先看是不是有分支没调 res.end(),比如参数校验失败只 return 了没响应,或者 catch 里只打了日志。每条路径都要以响应结束,出错也要回一个 500。

追问 3日志里出现 ERR_HTTP_HEADERS_SENT 是什么意思?
参考回答

响应已经发出去了又想再写头或再发一次,通常是 if 里响应完没 return,代码继续往下走又响应了一遍。响应语句后面紧跟 return 就好。

追问 4CPU 密集的活,比如生成报表、压缩图片,在 Node 里怎么做?
参考回答

放到 worker_threads 里跑,主线程只负责收发请求;量大的话干脆拆成独立服务或者走任务队列,接口先返回「已受理」。

追问 5未捕获的异常会怎样?用 process.on('uncaughtException') 兜住行不行?
参考回答

默认进程直接退出,Node 15+ 未处理的 Promise 拒绝也会让进程退出。uncaughtException 里只适合记日志然后退出,让 PM2 拉起来,别在里面吞掉继续服务,进程状态可能已经不可信了。

# 路由

30 秒速记

  • 路由 = 根据请求的「方法 + 路径」决定交给哪个函数处理
  • 服务端能拿到的是 method、pathname、查询参数和请求体;#hash 浏览器根本不会发给服务端
  • 原生写法:new URL(req.url, 'http://localhost') 拿 pathname,再 switch 或查表分发
  • 匹配不到返回 404;路径对但方法不对返回 405
  • 路由多了就用映射表或框架(Express / Koa / Fastify),别写一个巨大的 switch

路由说白了就是一张对照表:什么方法访问什么路径,就交给哪个函数处理。 比如 GET /students 查列表,POST /login 走登录。在原生 Node 里,路由就是自己解析 req.url 拿到 pathname,再结合 req.method 分发。有个常被问的点是 # 后面的锚点,它只在浏览器里用,请求根本不会带上,所以服务端没法按 hash 路由,前端单页应用的 hash 路由就是利用了这一点。接口少的时候 switch 够用,多了我会用一个 { 'GET /students': handler } 这样的映射表,再大就上框架。

在 BS 架构中,路由的概念都是一样的,可理解为根据客户端请求的 URL 映射到不同的方法实现,更多的一般都是针对 URL 中的路径,或者是参数,又或者是锚点这些信息进行映射。

面试官追问

追问 1前端访问 /orders#detail,后端能按 #detail 走不同逻辑吗?
参考回答

不能,# 后面的部分浏览器不会放进请求里,服务端收到的只有 /orders。真要区分就改成 /orders/detail 或 ?view=detail。

追问 2只按 pathname 分发,GET /students 和 DELETE /students 进了同一个函数,问题在哪?
参考回答

不同方法语义完全不同,一个查一个删,权限也不一样。路由键要带方法,比如 'GET /students',路径存在但方法不对就回 405,别默默当成查询处理。

追问 3/orders 能访问,/orders/ 却 404 了,怎么处理?
参考回答

这是尾斜杠没做规范化。在分发前统一去掉末尾的 /,或者对带斜杠的请求做 301 跳转到不带斜杠的版本,全站统一一种规则就行。

追问 4/students/8 这种带参数的路径,原生 switch 怎么匹配?
参考回答

switch 只能精确匹配,得用正则,比如 /^\/students\/(\d+)$/ 拿到 id。这种场景多了基本就该上 Express 之类的框架了,它们的 /students/:id 就是干这个的。

追问 5接口有几十个了,还在一个文件里 switch,你会怎么改?
参考回答

按业务模块拆,每个模块导出自己的路由表,入口合并注册;合并时检查有没有重复的「方法 + 路径」。到这个规模直接用 Koa / Express 的 Router 更省事,中间件、参数解析都现成。

# 场景

30 秒速记

  • 四个接口:POST /register、POST /login、GET /students、GET /orders,其余返回错误
  • POST 的请求体是分块流过来的:data 事件里累加 chunk,end 事件里再解析
  • 常见手误:写成 postData += '_data',拼进去的是字符串字面量,账号密码永远是空的
  • 未知路由要设置 404 状态码,只在 body 里写 {status: false} 会被监控当成成功
  • 返回 JSON 用 JSON.stringify + Content-Type: application/json,别用 util.inspect

这个场景就是用原生 http 模块,按「方法 + 路径」把注册、登录、查学生、查订单四个接口分发出去,匹配不到的返回错误。 GET 简单,参数在 URL 上,解析一下就能用。POST 要注意请求体不是一次到的,是一块块流进来的,得在 data 事件里把 chunk 拼起来,end 事件触发后再解析,比如 request.on('data', chunk => { body += chunk })。这里最容易手滑写成 '_data' 带引号的字符串,结果解析出来什么都没有。另外未知路由别只在响应体里写失败,状态码也要给 404。

  1. 注册一个账户 --> [post] --> http://localhost:88/register
  2. 注册成功的情况下跳转到登录界面进行登录 --> [post] --> http://localhost:88/login
  3. 登录成功进行获取学生信息 --> [get] --> http://localhost:88/students
  4. 同时可以获取订单信息 --> [get] --> http://localhost:88/orders
  5. 如何访问不存在的路由则抛出错误信息。
const http = require('http')
const url = require('url')
const qs = require('querystring');
const util = require('util');

http.createServer((request, response) => {
    let urlObj = url.parse(request.url, true);
    let pathname = urlObj.pathname;
    let method = request.method.toUpperCase();
    let params = urlObj.query;
    if(method == 'POST'){
        let postData = '';
        request.on('data', (_data) => {
            postData += '_data';
        })
        request.on('end', () => {
            postData = qs.parse(postData);
            let result = {};
            switch(pathname){
                case '/login':
                    //连接数据库,实现登陆逻辑
                    result = {status: true};
                    break;
                case '/register':
                    //连接数据库,实现注册逻辑
                    result = {status: true};
                    break;
                default :
                    result = {status: false, message: '没有对应的请求'};
                    break;
            }
            response.end(util.inspect(result))
        })
    } else {
        let result = {};
        switch(pathname){
            case '/students':
                //连接数据库,获取学生信息
                result = {status: true, data: [], params};
                break;
            case '/orders':
                //连接数据库,获取订单信息
                result = {status: true, data: [], params};
                break;
            default :
                result = {status: false, message: '没有对应的请求', params};
                break;
        }
        response.end(util.inspect(result))
    }
}).listen(88)
@前端进阶之旅: 代码已经复制到剪贴板

← node部署1.0 本地路径处理 path →

fe