Deng
Deng
全栈必备基础Node.js | odjBlog
    欢迎来到odjBlog的博客!

全栈必备基础Node.js

web前端学习 odjbin 4年前 (2022-03-25) 67次浏览 0个评论

Node.js 基础入门

nodejs 是什么

  • 一个基于 Chrome V8 引擎的 Javascript 运行时

    • 2009 年发布,现已更新到 V12 版本
    • 现已广泛应用于开源社区和各种公司,特别是互联网公司
  • Chrome V8

    • chrome 是一个浏览器,它可以执行 js 代码
    • V8 就是 chrome 的 js 引擎,以速度著称
    • nodejs 也是基于 js 语法的,因此也可以借用 V8 引擎
  • node 出现之前

    • nodejs 出现以前,只有浏览器可以执行 js 代码
    • 浏览器主要是显示网页,所有 js 也被当做网页的一部分
    • 除此之外,没有其他应用场景,更别提做服务端
  • node 出现之后

    • 除了浏览器,nodejs 又是一个新的 js 运行时
    • 哪里安装 nodejs,哪里就可以运行 js 代码
    • 可以用在本机(如使用 webpack 打包),也可以做服务端
  • nodejs 的价值

    • 让 js"放飞自我",不再是网页的一部分
    • 让 js 可以做更多的事情
    • 也让前端工程师可以做更多的事情

nodejs 初体验

  • cmd node index.js
const http = require('http')
const server = http.createServer((req, res) => {
  const url = req.url // '/index.html?a=100'
  const path = url.split('?')[0] //'/index.html'
  res.end(path+'-123')
})
server.listen(3000)

npm 介绍

  • node package manager,即 nodejs 软件包管理者

  • https://www.npmjs.com/

  • 软件包有何用

    • 现代软件工程已经完善且成熟,项目不会从 0 开始写
    • 必须搭配成熟的工具和框架才能满足需求,否则将无人使用
    • 每个成熟的开发语言或者环境,都需要成熟的软件包体系
  • 开始使用 npm

    • npm 会随着 nodejs 一起被安装
    • npm init 初始化环境
    • npm install lodash --save 安装 lodash

npm 安装 lodash

  • npm init 一路回车 yes

  • npm i lodash --save

  • 保证 lodash 在程序中会真正的引用出来,去使用
    "dependencies": {
    "lodash": "^4.17.21"
    },

  • lodash-test/test.js

const _ = require('lodash')
const arr = [1, 2, 3]
const otherArr = _.concat(arr, 4, 5)
console.log(otherArr)

npm 安装 nodemon

  • npm install nodemon --save-dev
 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev":"nodemon index.js"
  },
"devDependencies": {
    "nodemon": "^2.0.15"
  }

comonjs-回顾 ES6 模块化

  • commonjs 语法介绍
    • commonjs 和 ES6 Module 的区别
    • 为何要使用模块化

commonjs 语法介绍

  • module.exports

  • require(...)

  • 主要用于 nodejs 开发

  • require(...)的三个层级

    • 系统自带模块,如 require('http')
    • npm 包,如 require('lodash')
    • 自定义模块,如 require('a')
  • commonjs-test->utils.js

function sum (a, b) {
  return a + b
}
function test () {
  console.log('this is test')
}
module.exports = { sum, test }
  • commonjs-test->index.js
const { sum, test } = require('./utils')
test()
const res = sum(10, 30)
console.log(res)
const http = require('http')//nodejs 自带的模块
const _ = require('lodash')//通过 npm 安装的模块
const { sum, test } = require('./utils') //自己手写的模块 

commonjs 和 ES6 Module 的区别

  • 两者语法不一样
  • commonjs 是执行时引入,动态的
  • ES6 Module 是打包(提前)时引入,静态的

为何使用模块化

  • 模块拆分开,便于代码的组织和管理
  • 便于多人协作开发,各写各的互不干扰
  • 成熟的语言,都支持模块化,如 C, C++, Java, php, Python, Go

debug 介绍和演示

  • bug 即错误
    • debug 即排错,也叫调试
    • 编程语言,必须有成熟的 debug 机制,否则将不可用
  • debug 的重要性
    • 程序出 bug 很常见,因此 debug 也很常用
    • 出了 bug,得需要知道代码是如何运行出错的
    • 就像一台机器异响,得拆开外壳看看里面如何运转的
  • inspect 调试法
    • 修改 scrtips,增加--inspect,启动服务
    • 打开 chrome,访问 chrome://inspect
    • 增加 debugger,重启服务,即可调试
const http = require('http')
// const a = undefined
const server = http.createServer((req, res) => {
  // debugger//断点
  const url = req.url // '/index.html?a=100'
  const path = url.split('?')[0] //'/index.html'
  // a()
  res.end(path + '1234')
})
server.listen(3000)
console.log('server listening on 3000 port')

nodejs 和前端 js 的区别

  • 两者都使用 js 语法

    • 变量的定义和类型
    • 函数的定义和执行
    • ES6 的 Class Promise 等语法
  • 前端 js 使用浏览器提供的 Web API

    • 如前端网页的 DOM BOM 事件 Ajax 等
    • 前端 JS 可以使用,因为在浏览器环境
    • nodejs 则无法使用,因为是 nodejs 环境
  • nodejs 使用 nodejs API

    • 如处理 http
    • nodejs 可以使用,因为是 nodejs 环境
    • 前端 JS 则无法使用,.因为在浏览器环境
  • 前端 js=js 语法+Web API

  • nodejs=js 语法+nodejs API

  • 同样的语法,不同的工作

前后端那些事儿

为何要讲这门课

  • 前端和服务端那些事儿

    • nodejs 入门和使用
    • koa2 框架
    • 数据库
    • 登录和用户校验
    • 综合项目实战
  • 企业要求前端工程师,要会写服务端

    • 面试时,nodejs 已成为绝对加分项
    • 前端工程师的职业发展,离不开服务端
  • 企业需求

    • 节省人力成本
    • 节省沟通成本
    • 节省开发时间
  • 前端工程师的职业发展,离不开服务端

    • 前端不能脱离服务端独立存在
    • 做前端开发,必须了解服务端,亲密协作
    • 做前端架构师,必须熟悉,甚至引领服务端开发

课程安排

什么是服务端

  • 服务端,又称后端,server 端

    • 前端是用户可见, 可操作的部分,如树枝树叶
    • 服务端为前端提供"支撑"和"营养",如树根
  • 服务端的职责

    • 提供前端要展示的数据
    • 接收前端要提交的数据
    • 存储数据 ( 软件公司非常看重数据,会收集各种数据 )
  • 服务端的表现形式

    • 前端 ajax 要调用某个接口
    • 这个接口,就是服务端提供的
    • 如 get 请求获取数据,post 请求提交数据
  • 前端

    • 狭义: 网页
    • 广义: 各种客户端,如 App, PC 客户端等
    • 本课程中,前端即网页

留言板案例

  • 开发前端页面,如用 Vue
  • 需要 Ajax 的接口: 获取留言列表,提交留言
  • 开发服务端,提供接口

  • 小结
    • 服务端(后端/server)为前端提供支撑和营养,像一棵树
    • 服务端的职责: 提供数据,接收数据,存储数据

前后端如何交互-http 协议

  • 前端页面不一定只有一个服务端

  • http 协议-介绍

    • 超文本传输协议 HyperText Transfer Protocol
    • 规定了客户端和服务端如何通讯
    • 是互联网世界数据通讯的标准和基石
  • http 协议-通用

    • url : 后端接口的地址,即前端 Ajax 请求时的地址
    • method : 请求方法,如 GET POST PUT DELETE 等
    • 状态码 : 接口返回的状态, 如 200(成功) 302(重定向) 404(没找到) 500(发生错误)
  • http 协议 - Request

    • Request : 请求
    • Request Body : 请求是发送给后端的数据
    • Request Content-type : 发送数据的格式 , 如 json
  • http 协议 - Response

    • Response : 返回/响应
    • Response Body : 后端返回给前端的数据
    • Response Content-type : 返回数据的格式,,如 json

前后端如何交互-留言板示例

  • errno : 0 ( 即 error number 简写 )
  • data : { ... }
  • message : "..."

前后端如何交互一个页面对应多个服务

  • 不同资源可能来自不同的域名
    • html 可能来自一个单独的域名
    • js css 可能来自一个独立的域名
    • 数据可能来自一个独立的域名

服务端如何处理并返回数据

  • 定义前端请求的 url 规则--路由

  • 用 Request 获取数据,用 Response 返回数据

  • 读取和存储数据

  • 路由是什么

    • router
    • 服务端的入口规则
    • 和前端的约定
  • 路由包含什么

    • 定义 method,如 GET/POST 等
    • 定义 url 规则,如/api/list 和/api/create
    • 定义输入(Request body) 和输出 (Response body) 格式
  • 路由和 url

    • GET /api/list 路由 -> axios.get( '/api/list?a=1')
    • POST /api/create 路由 ->axios.get('/api/create',{...})
    • 路由是规则,url 是具体的形式
  • 路由-小结

    • 规定服务端的入口,入口即功能
    • 定义 method,url 规则,输入输出格式
    • 路由是规则,url 是具体的形式,两者不同

服务端如何处理数据- req 和 res

  • 服务端能得到 Request 和 Response

    • 也可简称为 req 和 res
    • 通过 Request 可获取: method url body
    • 通过 Response : 可设置: 状态码,Content-type,body
  • 路由规则的实现离不开 Request

    • 先定义路由规则(method,url)
    • 通过 Request 可获取: method url
    • 检查 method 和 url 是否符合哪个路由

服务端如何处理数据- 数据库

  • 数据库,专职做数据的存储和查询
  • 数据库是一个独立的系统,不是 nodejs 专属的
  • 先不管数据库是什么,就先以为是一个 JSON

为何选择 nodejs 做服务端

  • 不同语言,都能实现服务端职责
    • 处理 http 请求
    • 定义路由,供前端 Ajax 访问
    • 使用数据库,存储和查询数据
  • 不同语言,有哪些不同
    • 语言语法和内置 API
    • 框架
    • 工具包或软件包(如 npm)
  • 初学者学习服务端的重点
    • 掌握服务端的流程和套路
    • 能快速做出项目,在实践中进步
    • 不应该被语言,语法等喧宾夺主
  • nodejs 对于前端工程师的优势
    • nodejs 使用 JS 语法
    • nodejs 使用 npm
    • 还需要学习框架和 API

如何学习 nodejs-利用网络

  • 学习一门新技术的正确套路

    • 第一 , 找准范围
    • 第二 , 刻意训练
    • 第三 , 及时反馈
  • 善用文档

    • 程序员每天都会接触新东西
    • 必须学会看文档
    • 但注意,文档并不适合从 0 入门

Node.js 处理 HTTP

课程介绍

  • 定义路由
    • 拿到 req 中的 url 和 method
    • 定义路由(模拟留言板的获取留言列表,创建留言)
    • 测试路由(需要安装 postman)
    • querystring
  • 获取完整 url
    • 从 url 分析 query 参数
    • 直接使用 nodejs 自带的 querystring
  • 返回数据

    • 使用 res 设置返回的状态码,Content-type,Body
    • 如何返回 JSON 数据
    • 如何返回 html 数据
  • 获取 Request Body

    • 流 stream 的概念
    • 演示如何获取 Request Body
    • 使用 postman 测试

认识 req 和 res-监听 http 请求

  • nodejs 如何监听 http 请求
    • 如何拿到 req 和 res
    • 如何使用 req 和 res
  • nodejs 启动 Web 服务
    • 使用 http 模块,启动服务
    • 本机的 IP127.0.0.1
    • 本机的域名 localhost
const http = require('http')
const server=http.createServer(()=>{
  console.log('已经收到 http 请求')
  //还没有返回任何东西
})
server.listen(3000) //可以监听 http 请求
console.log('http 请求已经被监听,3000 端口, 请访问 http://localhost:3000')

认识 req 和 res-获取和使用

const http = require('http')
const server=http.createServer((req,res)=>{
  //console.log('已经收到 http 请求')
  const url=req.url //http://localhost:3000/index.html
  console.log('url is: ',url) // /index.html
  res.end('hello world')//res 返回信息给前端
})
server.listen(3000) //可以监听 http 请求
console.log('http 请求已经被监听,3000 端口, 请访问 http://localhost:3000')

路由-定义一个 get 路由

  • nodejs 定义路由
    • 从 req 中获取 url 和 method
    • 判断 method 是否符合
    • 看 url 是否符合规则
const http = require('http')
const server = http.createServer((req, res) => {
  const url = req.url
  const path=url.split('?')[0]
  const method = req.method
  // console.log('url is: ',url)//  /api/list?a=200
  // console.log('method is: ',method)
  //定义路由: 模拟获取留言板列表
  if (path=== '/api/list' && method === 'GET') {
    res.end('this is list router')
  } else { res.end('404') }
})
server.listen(3000) //可以监听 http 请求
console.log('http 请求已经被监听,3000 端口, 请访问 http://localhost:3000')

路由-定义一个 post 路由

  • get 请求,直接拿浏览器访问
  • post 请求,需要借助工具--postman
//定义路由:模拟创建留言
 if(path==='/api/create' && method==='POST'){
    res.end('this is create router')
  }

querystring-介绍和使用

  • 什么是 querystring

  • nodejs 获取 querystring

  • 论结构化与非结构化

    • url 问号?后面的都是 querystring (也叫 url 参数)
    • &分割,key=value 形式,可继续扩展
  • querystring 的作用

    • 动态网页的基石 (hash 就不行)
  • 如何利用 querystring 实现动态网页

    • 服务端拿到 querystring
    • 根据不同的 querystring,返回不同内容
    • 即变化 querystring,就是变换内容(只要服务端支持)
const http = require('http')
const server = http.createServer((req, res) => {
  const url = req.url
  const path = url.split('?')[0]
  const queryStr = url.split('?')[1]// a=100&b=200 非结构化
  // console.log('queryStr',queryStr)
  const method = req.method
  // console.log('url is: ',url)//  /api/list?a=200
  // console.log('method is: ',method)
  //解析 querystring
  const query = {}
  queryStr && queryStr.split('&').forEach(item => {
    //item 即 a=100 形式
    const key = item.split('=')[0]// 'a'
    const val = item.split('=')[1]// '100'
    query[key] = val//{a:'100',b:'200'} 结构化
  })
  // console.log('query is', query)
  //定义路由: 模拟获取留言板列表
  if (path === '/api/list' && method === 'GET') {
    if(query.filterType==='1'){
      res.end('this is list router,all')
    }
    if(query.filterType==='2'){
      res.end('this is list router,only mine')
    }
    // res.end('this is list router') //res 的返回
  } else { res.end('404') }
  //定义路由:模拟创建留言
  if (path === '/api/create' && method === 'POST') {
    res.end('this is create router')
  }
})
server.listen(3000) //可以监听 http 请求
console.log('http 请求已经被监听,3000 端口, 请访问 http://localhost:3000')

querystring-hash 不能传到服务端

 //解析 querystring
  const query = {}
  queryStr && queryStr.split('&').forEach(item => {
    //item 即 a=100 形式
    const key = item.split('=')[0]// 'a'
    const val = item.split('=')[1]// '100'
    query[key] = val//{a:'100'}
  })
===========================
const query=querystring.parse(queryStr)
  console.log('query is ',query)

querystring-结构化与非结构化

  • 结构化的数据,易于通过程序访问和分析,如对象和数组

  • 非结构化的数据,不易通过程序分析,如字符串

  • 编程中的数据,都尽量结构化

    • a=100&b=200 非结构化
    • { a : '100', b : '200' } 结构化
  • querystring 是 url ? 后面的参数

  • 动态网页的基石 (hash 就不行)

  • nodejs 处理 querystring,并将其结构化

res 返回数据-返回 json 格式

  • 使用 res 设置返回的状态码,Content-type,Body
//没有命中路由,默认 404
  // res.writeHead(404, { 'Content-type': 'text/plain' })
  // res.end('404 Not Found')

res 返回数据-返回 html 格式

const http = require('http')
const querystring = require('querystring')
const server = http.createServer((req, res) => {
  const url = req.url
  const path = url.split('?')[0]
  const queryStr = url.split('?')[1]
  const method = req.method
  const query = querystring.parse(queryStr)
  //定义路由: 模拟获取留言板列表
  if (path === '/api/list' && method === 'GET') {
    // res.end('this is list router') //res 的返回
    //返回结果
    const result = {
      errno: 0,
      data: [
        { user: '张三', content: '留言 1' },
        { user: '李四', content: '留言 2' }
      ]
    }
    res.writeHead(200, { 'Content-type': 'application/json' })
    res.end(JSON.stringify(result))
  }
  //定义路由:模拟创建留言
  if (path === '/api/create' && method === 'POST') {
    // res.end('this is create router')
    const result = {
      errno: 0,
      message: '创建成功'
    }
    res.writeHead(200, { 'Content-type': 'application/json' })
    res.end(JSON.stringify(result))
  }
  //没有命中路由,默认 404
  // res.writeHead(404, { 'Content-type': 'text/plain' })
  // res.end('404 Not Found')
  res.writeHead(404, { 'Content-type': 'text/html' })
  res.end(`
  <!DOCTYPE html>
  <html>
    <head>
    <title>404</title>
    </head>
    <body>
      <h1>404 Not Found</h1>
    </body>
    </html>
`)
})
server.listen(3000) //可以监听 http 请求
console.log('http 请求已经被监听,3000 端口, 请访问 http://localhost:3000')

接收 request body-流

  • 获取 Request Body

    • 流(stream)
  • 下载

    • source 即服务端,dest 即客户端(前端)
    • 水 即 下载的数据,水管 即 网络 (带宽不确定)
    • 下载不仅指大文件,泛指所有的 Response Body
  • 浏览器会接收 流(stream)数据

    • 服务端 res.end(...) , 会自动以流的形式返回
    • 浏览器会识别到 流 ,并持续接收信息(会有进度条)
    • 待全部接收完,再做显示或处理 (视频是一段一段的播放)
  • 上传

    • source 即客户端(前端) ,dest 即服务端
    • 水 即 上传的 数据,水管 即 网络 (带宽不确定)
    • 上传不仅指大文件,泛指所有的 Request Body
  • 服务端如何接收 流(stream) 数据

    • 前端使用 Ajax (Postman)提交数据 Request Body
    • 服务端需要识别 流 ,并接收数据
    • 还要知道何时才能接收完成

代码演示

const http = require('http')
const { chunk } = require('lodash')
const querystring = require('querystring')
const server = http.createServer((req, res) => {
  const url = req.url
  const path = url.split('?')[0]
  const queryStr = url.split('?')[1]
  const method = req.method
  const query = querystring.parse(queryStr)
  //定义路由:模拟创建留言
  if (path === '/api/create' && method === 'POST') {
    // res.end('this is create router')
    const reqType=req.headers['content-type']
    let bodyStr = ''
    req.on('data', chunk => {//服务端怎么去识别 "流",并接收数据
      //chunk 即"流"的每一段数据
      bodyStr = bodyStr + chunk.toString()
    })
    req.on('end', () => {//服务端怎么知道流完了
      if(reqType==='application/json'){//json 格式
        const body=JSON.parse(bodyStr)
        console.log('body is ', body)//对象格式
      }
      res.end('接收完成')//异步
    })
    return
  }
  res.writeHead(404, { 'Content-type': 'text/html' })
  res.end(`
  <!DOCTYPE html>
  <html>
    <head>
    <title>404</title>
    </head>
    <body>
      <h1>404 Not Found</h1>
    </body>
    </html>
`)
})
server.listen(3000) //可以监听 http 请求
console.log('http 请求已经被监听,3000 端口, 请访问 http://localhost:3000')
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
已稳定运行:3年255天3小时51分