NodeJS学习笔记2

Node学习笔记2

一、模块化回顾

注意:js文件的执行均是在命令行窗口,不是在vscode的终端噢!

执行js文件,要在文件目录下输入命令行:node b.js

1.初始化npm环境

在命令行输入:

npm init -y

2.安装在npm中常用的工具库lodash

npm i lodash --save
  • 使用lodash,在js文件中导入,lodash常用_表示

    const _ = require('lodash')
    

3.代码展示(01_commonjs-test):

  • a.js文件
function add(a, b) {
  return a + b
}

function mul(a, b) {
  return a * b
}

//只导出add方法
// module.exports = add

// 导出多个方法
module.exports = {
  add,
  mul
}
  • b.js

    const {add, mul} = require('./a')
    const _ = require('lodash')
    
    const sum = add(5, 6)
    const  ji = mul(2, 3)
    
    console.log(sum, ji);
    
    const arr = _.concat([1,2], 3)
    console.log('arr=', arr);
    

二、debugger调试

1.启用调试

在调试中选择Node.js,然后进入lauch.json文件。如下是一个已经配置好的lauch.json文件:

{
  // 使用 IntelliSense 了解相关属性。 
  // 悬停以查看现有属性的描述。
  // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "启动程序",
      "runtimeExecutable": "C:/Program Files/nodejs/node.exe",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "program": "${workspaceFolder}\\app.js"
    }
  ]
}

会遇到的问题主要有两点:

  • 首先,可能会报找不到node的错误。
  • 第二,会报找不到调试文件。

解决方法:

  • 对于问题1,首先打开命令行窗口,输入where node命令,找到node的位置。然后在配置中添加 "runtimeExecutable"属性。

    "runtimeExecutable": "C:/Program Files/nodejs/node.exe"
    
  • 对于问题2,调试工具的运行的位置在" w o r k s p a c e F o l d e r a p p . j s " , 其 中 {workspaceFolder}\\app.js",其中 workspaceFolderapp.js"{workspaceFolder}表示vscode打开的文件夹位置,你需要检查该路径是否为你需要调试文件的路径。

2.使用js自带的一个http模块在3000端口开启一个简单服务器,代码如下:

//http是自带的一个模块
const http = require('http')
const server = http.createServer((req, res) => {
  res.writeHead(200, {'content-type': 'text/html'})
  res.end('<h1>hello world!</h1>')
})

server.listen(3000, () => {
  console.log('listening on 3000 port');
})
  • 可以在res.writeHead处打一个断点,然后进行调试;同时使用Chrome浏览器打开localhost:3000网址。

三、前端和服务器端的五点区别

  • 服务稳定性
    • server端可能会遭受各种恶意攻击和误操作
    • 单个客户端可以意外挂掉,但是服务端不能
    • 使用PM2做进程守候,即当服务器挂掉时会自动重启
  • 考虑CPU和内存(优化、扩展)
    • 客户端独占一个浏览器,内存和CPU都不是问题
    • server端要承载很多请求,CPU和内存都是稀缺资源
    • 后续会讲使用stream写日志,使用redis存session
  • 日志记录
    • 前端也会参与写日志,但只是日志的发起方,不关心后续
    • server端要记录日志、存储日志、分析日志,前端不关心
    • 后续会讲多种日志记录方式,以及如何分析日志
  • 安全
    • server端要随时准备接收各种恶意攻击,前端则少很多
    • 如:越权操作(删除别人的博客),数据库攻击等
    • 后续会讲解登录验证,预防xss攻击和sql注入
  • 集群和服务拆分
    • 产品发展速度快,流量可能会迅速增加
    • 如何通过扩展机器和服务拆分来承载大流量
    • 本课题虽是但机器开发,但从设计上支持服务拆分

四、博客项目介绍

1.项目需求分析

目标:

  • 开发一个博客系统,具有博客的基本功能
  • 只开发server端,不关心前端

需求:

  • 首页,作者主页,博客详情页
  • 登录页
  • 管理中心,新建页,编辑页

总结:

  • 需求一定要明确,需求指导开发
  • 不要纠结于简单的页面样式,并不影响server端的复杂度

2.技术方案

  • 数据如何存储
    • 博客
    • 用户
  • 如何与前端对接,即接口设计

3.关于登陆

  • 业界有统一的解决方案,一般不用再重新设计
  • 但实现起来也比较复杂

五、开发接口(不用任何框架)

  • nodejs处理http请求
  • 搭建开发环境
  • 开发接口(暂不连接数据库,暂不考虑登陆)

六、http请求概述

面试常见问题1:输入URL按下enter之后发生了什么

  • 首先是DNS解析(将域名和ip地址相对应),建立TCP连接(发生三次握手),发送http请求
  • 然后server接收到http请求,处理,并返回
  • 最后,客户端接收到返回数据,处理数据(如渲染页面,执行js)

面试常见问题2:三次握手分别是什么?

  • 第一次握手:客户端询问服务器你是否可以用
  • 第二次握手:服务器告诉客户端自己可用
  • 第三次握手:客户端再次告诉服务器我知道了,接下来开始访问

七、nodejs处理http请求

  • nodejs处理get请求和querystring

    • get请求,即客户端要向server端获取数据,如查询博客列表

    • 通过querystring来传递数据,如a.html?a=100&b=200

    • 浏览器直接访问,就发送get请求

    • 如下是一个接口:

      // 导入nodejs自带的两个模块
      const http = require('http')
      const querystring = require('querystring')
      
      // 创建一个服务器对象,参数是一个函数
      const server = http.createServer((req, res) => {
        console.log(req.method);
        const url = req.url
        console.log('url:', url);
        // 根据'?'将url的参数分开,再转换成一个对象
        req.query = querystring.parse(url.split('?')[1])
        console.log('query:', req.query);
        res.end(
          // 将对象转成字符串
          JSON.stringify(req.query)
        )
      })
      
      server.listen(8000, () => {
        console.log('listening on 8000');
      })
      
      
  • nodejs处理post请求

    • post请求,即客户端要像服务端传递数据,如新建博客

    • 通过post data传递数据

    • 浏览器无法直接模拟,需要手写js,或者使用postman

    • 接口代码如下所示,对于该接口的访问请求可以使用postman

      • 打开postman,新建一个标签页

      • 选择post,输入http://localhost:8000/

      • 点击Body,选择raw,格式选择JSON

      • JSON内容输入

      • {

        “name”: “张三”,

        “age”: 25

        }

      • 最后点击send

      const http = require('http')
      
      const server = http.createServer((req, res) => {
        if(req.method === 'POST') {
          //req数据格式
          console.log('req content-type', req.headers['content-type']);
          let postData = ''
          req.on('data', chunk => {
            postData += chunk.toString()
          })
          req.on('end', () => {
            console.log('postData:', postData);
            res.end('hello world!')
          })
        }
      })
      
      server.listen(8000, () => {
        console.log('listening on 8000');
      })
      
  • nodejs处理路由

    • https://github.com/
    • https://github.com/username
    • https://github.com/username/xxx项目

八、blog-1项目

1.搭建开发环境

  • 从0开始搭建,不适用任何框架

  • 使用nodemon监测文件变化,自动重启node

    • 全局安装
    npm install -g nodemon
    
    • 本地安装
    npm install --save-dev nodemon
    
  • 使用cross-env设置环境变量,兼容mac linux 和 windows

    • 安装
    npm install --save-dev cross-env@5.2.0
    
    • 配置,在package.json中添加:

    “scripts”: {
    “dev”: “cross-env NODE_ENV=dev nodemon ./bin/www.js”,
    “prd”: “cross-env NODE_ENV=production nodemon ./bin/www.js”
    }

    
    
    

2.开发接口

主体分为四层,第一层是bin下的www.js,里面就是创建server的过程;第二层是app.js,根据url不同转向不同的路由;第三层是router,判断GET/POST请求,调用数据方法返回数据;第四层是controller,里面是对数据的处理方法。

  • **初始化路由:**根据之前技术方案的设计,作出路由。进行模块化拆分

    • bin/www.js文件,导入http模块,创建服务器server,开启监听

      const http = require('http')
      
      const PORT = 8000
      
      const serverHandle = require('../app')
      
      const server = http.createServer(serverHandle)
      
      server.listen(PORT)
      console.log('listening on 8000')
      
    • app.js文件,主入口是serverHandle()方法,表示如何处理数据

      const handleBlogRouter = require("./src/router/blog")
      
      const handleUserRouter = require("./src/router/user")
      
      const serverHandle = (req, res) => {
        // 设置返回格式JSON
        // JSON格式对于浏览器的解析比较友好
        res.setHeader('Content-type', 'application/json')
      
      
        // 处理blog路由
        const blogData =  handleBlogRouter(req, res)
        if(blogData) {
          res.end(
            JSON.stringify(blogData)
          )
          return
        }
      
        // 处理user路由
        const userData =  handleUserRouter(req, res)
        if(userData) {
          res.end(
            JSON.stringify(userData)
          )
          return
        }
      
        // 未命中路由,返回404
        res.writeHead(404, {"content-type": "text/plain"})
        res.write("404 Not Found\n")
        res.end()
      }
      
      module.exports = serverHandle
      
    • src/router文件下

      • blog.js文件,对/api/blog接口请求的处理方法

        const handleBlogRouter = (req, res) => {
          const url = req.url
          const method = req.method
          const path = url.split('?')[0]
        
          //获取博客列表
          if(method === 'GET' && path === '/api/blog/list') {
            return {
              msg: '这是获取博客列表的接口'
            }
          }
        
          // 获取博客详情
          if(method === 'GET' && path ==='/api/blog/detail') {
            return {
              msg: '这是获取博客详情的接口'
            }
          }
        
          // 新建一篇博客
          if(method === 'POST' && path === '/api/blog/new') {
            return {
              msg: '这是更新博客的接口'
            }
          }
        
           // 删除一篇博客
           if(method === 'POST' && path === '/api/blog/del') {
            return {
              msg: '这是删除博客的接口'
            }
          }
        
        
        }
        
        module.exports = handleBlogRouter
        
      • user.js文件,对/api/user接口请求的处理方法

        const handleUserRouter = (req, res) => {
          const url = req.url
          const method = req.method
          const path = url.split('?')[0]
        
          // 登陆
          if(method === 'POST' && path === '/api/user/login') {
            return {
              msg: '这是登陆的接口'
            }
          }
        }
        
        module.exports = handleUserRouter
        
  • 返回假数据:将路由和数据处理分离,以符合设计原则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值