二、node的简介

node是一个运行js的环境。浏览器也是运行js的环境。

两者的差别在于:

  • 浏览器会有window和document的调用。然而node没有
  • node有许多模块的api,例如文件系统拜访性能
  • node能够切换运行环境(切换版本?)
  • node不必bable转换
  • node应用的是commonJS,要应用require

2-2 nodejs与js的区别

nodejs = nodejsapi + ecmascript
解决http,解决文件等。

2-3 commonjs

module.export()require

2-4,5 debuger之inspect协定

--inspect==9229

chrome://inspect/#devices

四、开发博客我的项目之接口

4-1 http 概述

从url到浏览器的过程?

首先dns解析,解析完了发送申请,通过http协定建设tcp链接,而后传输文件。
浏览器拿到数据而后建设dom树,建设css树。合并成render树,而后渲染,注入js。

DNS解析,建设TCP连贯,发送http申请
server接管到http申请,解决并返回。
客户端接管到返回数据,解决数据,(如渲染页面,执行js)


Remote address 就是dns查问的后果

4-4 解决http申请的综合示例

const http = require("http");const port = 3000const server = http.createServer((req, res) => {    res.setHeader("Content-Type", "application/json")    const url = req.url    const method = req.method    res.end(`${url}${method}`);})server.listen(port, () => {    console.log(`服务器运行在 http://localhost:${port}/`)})console.log("ok")

4-5 搭建开发环境

  • 应用nodemon检测文件变动,主动重启node。
  • corss-env设置环境变量

npm i nodemon cross-env --save-dev

  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "dev": "cross-env NODE_ENV=dev nodemon  ./bin/www.js"  },

4-6 初始化路由

hostname:nodejs.cn
pathname:/api/blog/list
query:?name=zhangsan&keyword=123

const method = res.method  // post getconst url  = res.url // urlconst path = res.url.split("?")[0] // 

4-7 开发路由

创立SuccessModelErrorModel

class BaseModel {    constructor(data, message) {        if (typeof data === "string") {            this.message = data;            message = null;            data = null        }        if (data) {            this.data = data;        }        if (message) {            this.message = message;        }    }}class SuccessModel extends BaseModel {    constructor(data, message) {        super(data, message);        this.error = 0    }}class ErrorModel extends BaseModel {    constructor(data, message) {        super(data, message);        this.error = -1    }}module.exports = {    SuccessModel,    ErrorModel}

4-8 开发路由(博客详情路由)

const fs = require('fs');const path = require('path');function getFileContent(fileName) {    const fullFileName = path.resolve(__dirname, 'file', fileName)    const promise = new Promise((resolve, reject) => {        fs.readFile(fullFileName, (err, data) => {            if (err) {                reject(err);            }            resolve(JSON.parse(data));        })    })    return promise;}getFileContent('a.json').then(aDate => {    console.log(aDate);    return getFileContent(aDate.next);}).then((bData) => {    console.log(bData);    return getFileContent(bData.next);}).then((cData) => {    console.log(cData);});

4-9 开发路由(解决POSTData)

// 用于解决post dataconst getPostData = (req) => {    const promise = new Promise(() => {        if (req.method !== 'POST') {            resolve({})            return        }        if (req.headers['content-type'] !== "application/json") {            resolve({})            return        }    })    // 监听流数据    let postData = ''    res.on('data', chunk => {        postData += chunk.toString()    })    res.on('end', () => {        if (!postData) {            resolve({})            return        }        resolve(            JSON.parse(postData)        )    })    return promise}

更新和删除数据等....

5 数据库

MySql

use myblog;-- 查表-- show tables;-- insert into blogs(title,content,createtime,author)values("市民胡女士2的题目","市民胡女士2的内容",1585645673144,"mjmjmj");SELECT * FROM myblog.users LIMIT 0,1000;-- select username from users;-- select * from  users where password like '%1%' order by id desc;-- select * from blogs;-- ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password' PASSWORD EXPIRE NEVER;-- ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '11111111';-- flush privileges-- insert into blogs (title, content, createtime, author)values ('hhhhhh', 'jjhhhhh', 1585646800912, 'mjmjmj');-- select username, realname from users where username='mjmjmj' and password='321654a.'-- 更新-- SET SQL_SAFE_UPDATES = 0;-- update users set state = 0;-- update users set username ='huhuhu' where id = '2';-- 删除-- delete from blogs where id='1';

5.4 nodejs 操作 数据库

const mysql = require('mysql');const con = mysql.createConnection({    host: 'localhost',    user: 'root',    password: '11111111',    port: '3306',    database: 'myblog',})// 开始连贯con.connect()// 执行sqlconst sql = 'select * from users;';con.query(sql, (err, result) => {    if (err) {        console.log(err);        return;    }    console.log(result);})con.end();
const mysql = require('mysql');const { MYSQL_CONF } = require("../conf/db");// 创立链接对象const con = mysql.createConnection(MYSQL_CONF);// 建设连贯con.connect();// 对立执行sql 的函数function exec(sql) {    const promise = new Promise((resolve, reject) => {        con.query(sql, (err, result) => {            if (err) {                reject(err);                return            }            resolve(result)        })    })    return promise;}con.end();module.exports = {    exec}

6.2 Cookie 介绍

什么是cookie?
js如何操作cookie,如何在浏览器中查看cookie?
server端操作cookie,实现登录验证、

特点:

  1. 最大5kb
  2. 跨域不共享,
  3. 可保留结构化数据
  4. 每次发送http申请,会将申请域的cookoie 一起发送给cookie
  5. server 端能够批改cookie,并返回给客户端
  6. 客户端也能够通过js批改cookie,并返回给server端(有限度)
  7. 看申请的哪个域,申请哪个域,带哪个cookie
申请头外部的cookie

本地的缓存cookie

domin:cookie失效的域名
path:是cookie失效门路

批改cookie


有了localStorage ,本地批改cookie的状况不多

nodejs批改cookie
// 解析 cookie    req.cookie = {}    const cookieStr = req.headers.cookie || ''  // k1=v1;k2=v2;k3=v3    cookieStr.split(';').forEach(item => {        if (!item) {            return        }        const arr = item.split('=')        const key = arr[0].trim()        const val = arr[1].trim()        req.cookie[key] = val    })
nodejs setCookie
    // 登录    if (method === 'POST' && req.path === '/api/user/login') {        const { username, password } = req?.body        const result = login(username, password)        return result.then(data => {            if (data.username) {                // 操作cookie                res.setHeader('SetCookie', `username=${data.username}`)                return new SuccessModel()            }            return new ErrorModel('登录失败')        })    }

6.4 cookie 做限度

设置httpOnly

res.setHeader('SetCookie', `username=${data.username}; path=/; httpOnly`)
// 获取 cookie 的过期工夫const getCookieExpires = () => {    const d = new Date()    d.setTime(d.getTime() + (24 * 60 * 60 * 1000))    console.log('d.toGMTString() is ', d.toGMTString())    return d.toGMTString()}
    res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)

6.6 session

cookie 中 会裸露username,很危险
useridsidconentid,对应server端username.

  • session间接是js变量,放在nodejs过程内存中;
  • 内存过大,会把过程的空间挤爆
  • 多过程之间,数据无奈共享

6.8 redis

redis 解决多过程不可能互通session的问题(挤爆,多过程之间无奈数据共享。),是服务端罕用的缓存工具。

web server 最罕用的缓存数据库,数据寄存在内存中,相比mysql 读写速度快,然而比拟低廉,断电失落。

  • 独自的服务,与nodejs之间只是调用关系。就像mysql一样,所以不存在被挤爆的状况。
  • 多过程之间拜访同一个redis。所以session会同步。
  • redis 可拓展,就算用户量减少,那也能够减少机器,能够拓展成集群。

session 对性能的要求极高,因为每次都会发送申请。断电失落没关系,从新登录即可。所以不可能间接存在mysql中。

6.9

const redis = require('redis');const { REDIS_CONF } = require('../conf/db');// 创立客户端const redisClient = redis.createClient(REDIS_CONF);redisClient.on('error', (error) => {    console.log(error);})function set(key, val) {    if (typeof val === "object") {        val = JSON.stringify(val);    }    redisClient.set(key, val, redis.print);}function get(key) {    const promise = new Promise((resolve, reject) => {        redisClient.get(key, (err, val) => {            if (err) {                reject(err)                return            }            if (val == null) {                resolve(null);                return            }            try {                resolve(JSON.parse(val))            } catch (ex) {                resolve(val)            }            resolve(val);        })    });    return promise;}module.exports = {    set,    get}
set myname mjget myname // mjget * // 获取所有key value
    // 获取 session    req.sessionId = userId    get(req.sessionId).then(sessionData => {        if (sessionData == null) {            // 初始化 redis 中的 session 值            set(req.sessionId, {})            // 设置 session            req.session = {}        } else {            // 设置 session            req.session = sessionData        }        // console.log('req.session ', req.session)        // 解决 post data        return getPostData(req)    })        .then(postData => {        ......  }

6.14 为什么应用nginx

因为前端起的一个服务和nodejs起的服务不是同一个端口,而cookie跨域不共享。

应用http-server 起一个前端的服务。端口设置为8001。
nodejs:8000 端口

大家都去8080端口。

6.15 高性能的web服务器nginx),开源,收费

如果申请/根目录,申请html,那么,nginx间接返回返回html

如果申请/api/blog/...先到nginx端口8000,而后再到node服务的端口,8001.

对客户端不可见的代理,称为反向代理

应用easyconnect连贯,被称为正向代理,客户端能够管制

  • 测试配置文件格式是否正确: ngnix -t
  • 启动nginx 重启 nginx -s reload
  • 进行 ngnix -s stop
sudo vi /usr/local/etc/nginx/nginx.conf

次要就是增加这些代码,而后把下面的一些正文掉。

location / {    proxy_pass <http://localhost:8001>;}location /api/{    proxy_pass <http://localhost:8000>;    proxy_set_header Host $host;} 

感觉搞了半天,就是看懂了什么是redis,什么是session,什么是ngnix,代码外面就是配一配。