前端入门(四)Node 基础

256 阅读4分钟

四、Node基础

node 一般用于中间层、小型服务器、工具类的开发

4.1 npm 基本命令

npm 是 JavaScript 世界的包管理工具,并且是 Node.js 平台的默认包管理工具

  1. 换源
npm install cnpm -g --registry=https://registry.npm.taobao.org
  1. 安装
  • npm install xxx
  • npm i xxx
  1. 删除
  • npm uninstall xxx
  • npm un xxx
  1. 更新
  • npm update xxx
  1. 初始化项目
  • npm init

    //package.json
    {
      "name": "test",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
       
    //npm i koa -d 后会自动生成在这儿
      "devDependencies": {
         "koa": "^2.11.0" // ^ + 兼容版
      }
    }
    

4.2 node 模块

4.2.1 使用模块

  • 引入

带路径需要去路径下找,如果没有从 node_modules 文件夹找,还没有的话会从系统的 node_modules 文件夹找

const xx = require('xx'); 
  • 导出
//mod.js
exports.a = 1;

//app.js
const mod = require('./mod')
console.log(mod.a)
  • 批量导出
module.exports = {
    a:'1'
};//可以导出json

module.exports = function(){
    
};//可以导出函数

module.exports = class{
  constructor(name){
      this.name = name;
  }  
};//可以导出类

4.2.2 系统模块

  • assert 断言
const assert = require('assert');

assert('条件','errlog'); //通过不执行,不通过打印错误日志

//深度比较
assert.deepStrictEqual(变量,预期值,msg)
  • path 路径
const path = require('path')
let str = '/root/a/b/1.txt'
console.log(path.dirname(str)) //输出:/root/a/b
console.log(path.extname(str)) //输出:.txt
console.log(path.basename(str))//输出:1.txt
console.log(path.resolve(__dirname,'build')) 
//当前目录的绝对路径/build

4.3 数据通信

4.3.1 http 模块

const http = require('http')
let server = http.createServer((req, resp) => {
    //服务器返回
    resp.write('返回数据');
    resp.end()
});
server.listen(8080);

4.3.2 fs 文件读写模块

const fs = require('fs');
//写入相同的文件将会覆盖
fs.writeFile('./test.txt', 'abc你好啊', err => {
    if (err) {
        console.log("失败")
    } else {
        console.log("成功")
    }
})

fs.readFile('./test.txt', {
    encoding: 'utf-8'
}, (err, data) => {
    console.log(data)
})

文件流的读写

const fs = require('fs');
const zlib = require('zlib');

let rs = fs.createReadStream('3.txt');
let ws = fs.createWriteStream('2.txt');
//let gz = fs.createGzip(); 压缩
rs.pipe(ws);

//rs.pipe(gz).pipe(ws); 压缩
rs.on('error',err=>{
   console.log(err); 
});
ws.on('finish',()=>{
    console.log('完成');
});

4.3.3 解析get/post请求

  • url模块解析 get 请求
const http = require('http');
const url = require('url');

http.createServer((req, resp) => {
	let get = url.parse(req.url,true)
    console.log(get)
}).listen(8080);
  • post 发送的是body,并且可能分批次请求
const http = require('http');
const url = require('url');
const querystring = require('querystring');
let arr=[];
http.createServer((req, resp) => {
	req.on('data',buffer=>{
        arr.push(buffer)
    })
    //post请求完毕,将每批的结果拼接起来
    req.on('end',()=>{
        let buffer = Buffer.concat(arr);
        let post = querystring.parse(buffer.toString());
        console.log(post);
    })
}).listen(8080);

4.3.4 解析文件请求

提交表单

<form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="file" name="f1">
    <input type="submit" value="提交">
</form>

后端处理

const http = require('http');
const multiparty = require('multiparty')
http.createServer((req, resp) => {
    let form = new multiparty.Form({
        uploadDir: './upload'//上传到的位置
    })
    form.parse(req);
    form.on('field', (name, value) => {
        console.log('field', name, value)
    })
    form.on('file', (name, file) => {
        console.log('file', name, file)
    })
    form.on('close', () => {
        console.log("表单解析完成")
    })
}).listen(8080);

4.3.5 ajax 跨域问题

原生 ajax 请求

<script>
    let btn1 = window.document.getElementById('btn1');
    btn1.onclick = () => {
        //原生 ajax
        let ajax = new XMLHttpRequest();
        ajax.open('GET', 'http://localhost:8080/a', true);
        ajax.send();
        ajax.onreadystatechange = () => {
            //0~4
            if (ajax.readyState === 4) {
                if (ajax.status >= 200 && ajax.status < 300 || ajax.status === 304){
                    alert('成功');
                    alert(ajax.responseText);
                }else{
                    alert('失败');
                }
            }
        }
    }
</script>

后端给浏览器返回一个声明,解决跨域问题

const http = require('http');
http.createServer((req, resp) => {
    let res = {
        a: '1',
        b: '2'
    };
    resp.setHeader('access-control-allow-origin', "*"); //解决跨域问题,全部允许
    resp.write(JSON.stringify(res));
    resp.end();
}).listen(8080);

4.3.6 fetch

fetch 可以解析多种数据,文本、json、图片等

<script>
    let btn1 = window.document.getElementById('btn1');
    btn1.onclick = async () => {
        let result = await fetch('./data/1.json');
        // let str = await result.text(); 解析文本
        //let json = await result.json(); 解析 json
        let blob = await result.blob();
        let url = URL.createObjectURL(blob);
    }
</script>

4.3.7 FormData(Ajax2.0)

上传表单的新姿势

<script>
    //原生
    let mForm = document.querySelector('#mform');
    mForm.onsubmit = function () {
        //拿到form数据
        let formdata = new FormData(mForm);
        let xhr = new XMLHttpRequest();
        xhr.open(formdata.method, formdata.action, true);
        xhr.send(formdata)
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    alert('成功');
                } else {
                    alert('失败');
                }
            }
        }
    }
    //jquery
    $('#mform').on('submit', () => {
        let formdata = new FormData(this);
        $.ajax({
            url: this.action,
            type: this.method,
            data: formdata,
            processData: false,
            contentType: false
        }).then(success => {
            alert('成功');
        }, fail => {
            alert('失败');
        });
    });
</script>

4.3.8 webSocket

性能高、双向通信(客户端可以向服务端发请求,服务端也能向客户端主动发数据)、TCP、一对一

安装socket.io:npm i socket.io -D

客户端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="http://localhost:8080/socket.io/socket.io.js" charset="utf-8"></script>
</head>
<body>
<script>
    let socket = io.connect('ws://localhost:8080');
    socket.emit('c2s', 1, 2, 3);
    socket.on('s2c', data => {
        console.log(data);
    })
</script>
</body>
</html>

服务端

const http = require('http');
const io = require('socket.io')

//1.建立普通的 http
let server = http.createServer((req, resp) => {
});
server.listen(8080);
//2.建立webSocket
let webSocketServer = io.listen(server);
webSocketServer.on('connection', socket => {
    //主动发送数据
    setInterval(()=>{
        socket.emit('s2c', new Date().getTime())
    },1000);
    //接收客户端数据
    socket.on('c2s', (data1,data2,data3) => {
        console.log(data1,data2,data3);
    })
});

4.4 数据库

4.4.1 分类

  1. 文件型: acess、sqlite;适合单机存储少量数据,容易迁移

  2. 关系型数据库:MySql、Oracel;支持复杂查询,性能一般

  3. 分布式:mongoDB;单机性能不高,可以合起来形成存储网络

  4. NoSQL:redis;简单查询,性能高

4.4.2 Node 使用数据库

const mysql = require('mysql');
//连接到服务器
let db = mysql.createConnection({
    host: 'localhost',
    port: 3306,//default
    user: 'root',
    password: 'root',
    database: 'wuai'
});
//查询
db.query('SELECT * FROM user_info', (err, data) => {
    console.log(err, data);
});

优化

const http = require('http');
const mysql = require('mysql');
const co = require('co-mysql');

//建立连接池
let conn = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'root',
    database: 'wuai'
});
//异步调用
let db = co(conn);
http.createServer(async (req,resp)=>{
    let data = await db.query('SELECT * FROM user_info WHERE id = 1');
}).listen(8080);