3 Star 4 Fork 1

SamuelSue / 前端面试

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Node.js.md 28.35 KB
一键复制 编辑 原始数据 按行查看 历史
SamuelSue 提交于 2019-09-19 21:15 . add node vue

Node.js

[TOC]

入门

环境配置

nvm管理多版本node

https://github.com/coreybutler/nvm-windows/releases/

以非安装版压缩包为例:

image.png

管理员运行install.cmd, 直接回车, 然后修改配置如下, 将其保存到nvm目录下

root:  C:\node\nvm  # nvm目录
path:  C:\node\nodejs  # nodejs版本快捷方式
arch: 64 
proxy: none
node_mirror: http://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/

修改环境变量:

NVM_HOME: C:\node\nvm
NVM_SYMLINK : C:\node\nodejs
PATH: ......;%NVM_HOME%;%NVM_SYMLINK%

控制台查看nvm version即可

nvm安装node.js

使用命令: nvm install [node版本号]即可

模块化开发

全局对象概述

// 全局成员概述

console.log(__filename);
console.log(__dirname);

console.log(process.argv); // 是一个数组, 分别为node.exe路径, js文件路径, 后面还会有命令行参数
console.log(process.arch);

exports导出模块

var sum = function (a,b) {
    return a+b;
}

// 导出模块方法一, 原本每个js都是相互独立的, 这里相当于暴露接口给外部使用
exports.sum = sum;

导入模块调用:

// 引入模块方法一
var module = require('./sum_module');
console.log(module.sum(3,4));

modules导出模块

var sum = function (a,b) {
    return a+b;
}

// 导出模块方法二(注意对应)
module.exports = sum;
// module.exports = {a:12,b:5}; // 可批量导出

导入模块调用

var sum = require('./sum_module'); // 此时的sum就是上面的module.exports
console.log(sum(3,4));

全局globals导出模块(了解)

var sum = function (a,b) {
    return a+b;
}
globals.sum = sum;


// =========================

require("./sum_module");
console.log(globals.sum(2,3));

模块格式

node.js支持的模块格式有.js, .json(解析为对象), .node(C编译得到)

ES6语法

因为Node.js是在ES6语法基础上建立起来的, 因此需要了解ES6语法

变量声明

新的语法letconst

// let不会预解析
console.log(flag);
let flag = 1;


// let声明变量在同一作用域内不能重复
let flag = 1;
let flag = 2;

// ES6引入块级作用域
if(1){
    var flag = 1;
}
console.log(flag);

if(1){
    let flag1 = 1;
}
console.log(flag1);  // 访问不到块级作用域下的let声明变量

{
    //这也是一个块级作用域
    let flag2 = 'hello'
}

const除了上面的特性, 使用它声明的是常量, 无法被修改, 并且在声明时就要初始化

块级作用域的好处体现:

// 假如页面上有4个按钮, 要求每个按钮按下弹出alert:0,1,2,3
// 之前我们使用var, 需要配合闭包才能实现
// 使用let, 直接方便快捷实现
for(let i=0, length=btns.length;i<length;i++){
    btns[i].onclick = function(){
        alert(i);
    }
}

解构赋值

数组的解构赋值

// 数组的解构赋值
let [a,b,c] = [1,2,3];
console.log(a);
console.log(b);
console.log(c);

let [e=33,f,g] = [,123,];
console.log(e,f,g);  // 33,123,undefined

对象的解构赋值(与顺序无关)

// 对象的解构赋值(与顺序无关)
let {foo,bar} = {foo:"hello",bar:"hi"};
console.log(foo,bar);

// 对象别名:
let {foo:abc,bar1} = {foo:"hello",bar1:"hi"};  //foo有了别名abc, 原来的名字foo则失效
console.log(abc,bar1);

let {cos,sin} = Math;
console.log(typeof cos);

字符串的解构赋值:

let {a,b,c} = "hello";
console.log(a,b,c); // 'h','e','l';

let {length} = 'hello';
console.log(length);  // length关键字为Number类型, 所以这里解构为string.length;

字符串拓展

str.includes(searchingStr,index): 判断str中是否存在searchStr, 从index处开始搜索

startsWith()/endsWith(): 判断开头和结尾.

模板字符串:

// 模板字符串
let person = {
    name: "Samuel",
    age: "24",
};
// 类似前端的js模板拼接结构
let tpl = `<div><span>${person.name}</span><span>${person.age}</span></div>`;
console.log(tpl);

${}中可以做一些简单的数值运算和函数调用.

数组拓展

arr.map(callback(value,index,arr));

arr.forEach(callback(value,index)); // 遍历时无法终止

arr.filter(callback(value,index,arr));

arr.some(callback(value, index, arr)); // 遍历数组, 若有一个值符合条件则返回true.可提前终止遍历

arr = [1,2,3];
arr.some(value=>{
    if(value>1){
        return true; // 此时遍历会终止.
    }
})

arr.every(callback(value,index,arr)); // 遍历数组, 若有一个值满足条件则返回false. 可提前终止遍历

arr = [1,2,3];
arr.every(value=>{
    if(value>1){
        return false; // 此时遍历会终止.
    }
})

arr.reduce(callback(tmp,value,index,arr));

reduce (让数组中的前项和后项做某种计算,并累计最终值)

callbackFunction 包含4个参数

prev:第一项的值或者上一次叠加的结果值 cur: 当前会参与叠加的项 index: 当前索引 arr: 数组本身

// 求平均数
let arr = [1, 2, 3, 4, 5, 6, 7];
result = arr.reduce((tmp, value, index) => {
    if (index < arr.length - 1) {
        //console.log(tmp, value);
        return tmp + value;
    } else {
        return (tmp+value) / arr.length;
    }
});
console.log(result);

函数拓展

参数默认值:

function foo(param = 'nihao'){
    console.log(param);
}

rest参数(剩余参数)

function foo(a,b,...param){
    console.log(param);
}
foo(1,2,3,4,5,6); // [3,4,5,6]

扩展运算符...

function foo3(a,b,c,d,e){
    console.log(a+b+c+d+e);
}
let arr = [1,2,3,4,5];
foo3(...arr);

箭头函数

let foo = (a, b) => {
    let c = 1;
    console.log(a + b + c);
}
foo(1,2);

let arr1 = [123,456,789];
arr1.forEach((value,index)=>{
    console.log(value,index);
});

箭头函数注意点:

  1. 箭头函数中的this取决于函数的定义, 而不是调用
function test() {
    setTimeout(() => {
        console.log(this);
    }, 100);
}

test.call({num: 1}); // 此时箭头函数定义在test函数内部, this指向test函数的第一个参数
  1. 箭头函数不可以new
  2. 箭头函数不能用arguments获取参数列表, 但是可以使用rest参数代替
let test1 = (...param) => {
    console.log(param);
}
test1(123, 3345);

类与继承

// class关键字

class Animal {
    // 构造函数
    constructor(name) {
        this.name = name;
    }

    // 方法
    showName() {
        console.log(this.name);
    }

    // 静态方法
    static eat(a) {
        console.log(a + "吃东西");
    }
}

let a = new Animal('dog');
a.showName();
// 静态方法
Animal.eat("dog");

// 类的继承
class Dog extends Animal {
    constructor(name, color) {
        super(name);
        this.color = color;
    }
    bark(){
        console.log('a ' + this.color + ' dog is barking');
    }
}
let d = new Dog('hehe','black');
d.bark();

Promise

传统的JS都是单线程执行, 通过回调函数来实现异步, 但是这种写法很恶心, 每次都要写回调, 就不能创建一个任务, 然后判断任务.isSucess? 这时候就要引入Promise了

// 创建Promise对象
let p=new Promise(function (resolve, reject){
    $.ajax({
        url: 'data/1.json',
        dataType: 'json',
        success(data){
            resolve(data);  // 参数传递到resolve中
        },
        error(res){
            reject(res);	// 异常传递到reject中
        }
    });
});
// then中传递连个函数, 分别对应上面的resolve和reject
p.then(function (data){
    alert('成功');
    console.log(data);
}, function (res){
    alert('失败');
    console.log(res);
});

同时Promise还有一个all接口, 负责封装多个异步任务, 统一获取数据

Promise.all([
    $.ajax({url: 'data/1.json', dataType: 'json'}),
    $.ajax({url: 'data/2.json', dataType: 'json'}),
    $.ajax({url: 'data/3.json', dataType: 'json'}),
]).then((arr)=>{
    let [data1, data2, data3]=arr;
    console.log(data1, data2, data3);
}, (res)=>{
    alert('错了');
});

但是, 上述Promise封装的任务是互不相关的, 实际开发中遇到的任务其实是相互联系的, 比如获取用户的登录状态,获取商品列表, 根据用户是否登录推荐不同的商品.

async和await

为了解决Promise的局限性问题, es6产生了async和await语法糖(实际还是会编译成回调形式的代码).使用方式如下:

async function show(){
    let data1=await $.ajax({url: 'data/1.json', dataType: 'json'}); // await修饰的是一个Promise对象.它最主要的意图是用来等待 Promise 对象的状态被 resolved
    let data2=await $.ajax({url: 'data/2.json', dataType: 'json'});
    let data3=await $.ajax({url: 'data/3.json', dataType: 'json'});

    console.log(data1, data2, data3);
}

show();

示例: 根据上一个异步请求的状态执行不同的异步操作

async function show(){
    let data1=await $.ajax({url: 'data/1.json', dataType: 'json'});
    if(data1.a<10){
        let data2=await $.ajax({url: 'data/2.json', dataType: 'json'});
        alert('a');
    }else{
        let data3=await $.ajax({url: 'data/3.json', dataType: 'json'});
        alert('b');
    }
}

ES7字符串补充

str.padStart(length, padStr)/padEnd(length, padStr): 填充padStr至长度length

数据通信

fetch

用于替代XMLHTTPRequest而产生的js api, https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

let oImg=document.getElementById('img1');
let oBtn=document.getElementById('btn1');
oBtn.onclick=async function (){
    //1.请求
    let res=await fetch('data/1.png'); // Promise对象 可以请求txt json 二进制数据 
    //2.解析
    let data=await res.blob();  // blob, json, text
    let url=URL.createObjectURL(data);

    oImg.src=url;
};

jsonp

本质上就是在本地写好回调函数, 然后通过<script>引入外部js调用回调函数

function show({s}){
    console.log(s);
}

window.onload=function (){
    let oTxt=document.getElementById('txt1');
    oTxt.oninput=function (){
        let url=`https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${this.value}&cb=show`;  // 百度搜索词联想
        let oS=document.createElement('script');
        oS.src=url;

        document.head.appendChild(oS);
    };
};

jQuery写法:

$('#txt1').on('input', function (){
    $.ajax({
        url: 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
        data: {wd: $(this).val()},
        dataType: 'jsonp',
        jsonp: 'cb'
    }).then(({s})=>{
        console.log(s);
    }, res=>{
        alert('失败');
    });
}

formData

配合<form>可以更加轻松的完成表单提交, 处理文件上传也更加方便

let oForm=document.querySelector('#form1');  // form表单

oForm.onsubmit=function (){
    let formdata=new FormData(oForm);  // 通过form表单创建FormData对象

    let xhr=new XMLHttpRequest();  // 原生ajax发送数据

    xhr.open(oForm.method, oForm.action, true);  // 通过form获取url和method, async=true.
    xhr.send(formdata);  // 发送formdata

    xhr.onreadystatechange=function (){
        if(xhr.readyState==4){
            if(xhr.status==200){
                alert('成功');
            }else{
                alert('失败');
            }
        }
    };

    return false; // 阻止默认提交
};

jQuery写法

$('#form1').on('submit', function (){
    let formdata=new FormData(this);

    $.ajax({
        url: this.action,
        type: this.method,
        data: formdata,
        processData: false, // 防止jquery处理数据
        contentType: false  // 防止jquery添加contenttype
    }).then(res=>{
        alert('成功');
    }, res=>{
        alert('失败');
    });

    return false;
});

手动构建:

let formdata=new FormData();  // 创建空的formdata

formdata.append('username', document.querySelector('#user').value);  // 手动添加数据
formdata.append('password', document.querySelector('#pass').value);
formdata.append('f1', document.querySelector('#f1').files[0]);  // 手动添加文件

//
let xhr=new XMLHttpRequest();

xhr.open('post', 'http://localhost:8080/', true);
xhr.send(formdata);

NPM包管理

https://www.npmjs.com/

npm安装方式

  1. 本地安装(npm install XXX) 安装到当前目录的node_module中
  2. 全局安装(npm install -g XXX) 一般用于有cmd命令的包, 安装到nodejs的node_modules目录下

常用命令:

  • npm uninstall (-g) 卸载
  • npm update (-g) 更新
  • npm install (-g) XXX@版本号
  • npm install xxx --save (将包名保存到package.json中的依赖中)
  • npm install xxx --save-dev (安装开发所用的包)

cnpm管理

npm install -g cnpm --registry=https://registry.npm.taobao.org

之后把所有的npm命名换成cnpm即可, 推荐使用cnpm, 可以解决下载速度慢的问题

基本接口

Buffer基本操作

Buffer对象是Node处理二进制数据的一个接口**(操作字节)**。它是Node原生提供的全局对象,可以直接使用.

实例化Buffer:

  • Buffer.from(array)
  • Buffer.from(string)
  • Buffer.alloc(size): size表示字节数, 即创建一个size字节的Buffer

功能方法:

  • Buffer.isEncoding() 判断是否支持该编码
  • Buffer.isBuffer() 判断是否为Buffer
  • Buffer.byteLength() 返回指定编码的字节长度,默认utf8
  • Buffer.concat() 将一组Buffer对象合并为一个Buffer对象

实例方法:

  • write() 向buffer对象中写入内容
  • slice() 截取新的buffer对象
  • toString() 把buf对象转成字符串
  • toJson() 把buf对象转成json形式的字符串

utf8编码中, 英文字母占用1个字节, 汉字占用3个字节

路径操作

https://nodejs.org/dist/latest-v10.x/docs/api/path.html

const path = require('path');

path.basename(path[, ext]): 返回路径的最后一部分(文件名)

path.dirname(path): dirname+basename = 完整的absolute path;

path.delimiter: 环境变量分隔符

path.extname(path): 文件后缀

path.parse(path): 从路径string解析为pathObject

path.format(pathObject): 从pathObject格式化为路径string

path.isAbsolute(path)

path.join([...paths]): 路径拼接

path.normalize(path): 规范化路径

path.relative(from, to): from到to的相对路径

path.resolve([...paths]): 类似cd命令, 返回cd完所有path之后的最终相对路径(相对工作目录)

path.sep: 路径分隔符

文件操作

https://nodejs.org/dist/latest-v10.x/docs/api/fs.html

const fs = require('fs');

Node.js的异步操作是基于事件队列和回调实现的, 因此一般异步操作函数的写法如下:

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

// 读取文件
let strpath = path.join(__dirname, 'data.txt');

fs.readFile(strpath, (err, data) => {
    if (err) return;
    // console.log(data); // data是一个Buffer对象
    console.log(data.toString())
});
// 第二个参数可以是编码, 此时data则是字符串
fs.readFile(strpath, 'utf8', (err, data) => {
    if (err) return;
    console.log(data)
})

// 同步写入文件
fs.writeFileSync(strpath, ' this is my life', {encoding: 'utf8', flag: 'a'});

文件的流操作

针对大文件, 无法一次全部读入内存, 因此采用流的操作方式, 降低开销

// 大文件的流式操作
const fs = require('fs');
const path = require('path');

let file_path = 'F:\\Download\\前端\\【05】WebAPI.rar';
let dest_path = path.join('e:/','test.rar');

// 创建读取流和写入流
let readStream = fs.createReadStream(file_path);
let writeStream = fs.createWriteStream(dest_path);

// 基于事件的处理方式
readStream.on("data",(chunk)=>{
    // 读取文件块, 然后写入
    writeStream.write(chunk);
})
readStream.on("end",()=>{
    writeStream.close();
    console.log("复制完成");
})

除了上述完整写法, 可以简化为一句: readStream.pipe(writeStream);

目录操作

fs.mkdir();

fs.readdir(); 读取目录

fs.rmdir(); 删除目录

http

原生node.js封装的创建http服务器的模块, 使用方法:

// 初步实现服务器的功能

const http = require('http');
// 创建服务器实例
let server = http.createServer();
// 绑定请求事件
server.on('request',(req,resp)=>{
    resp.end("hello");
})
// 监听端口
server.listen(3000);

简写版:

const http = require('http');

let server = http.createServer(function (req, resp) {
    resp.write("hello"); // 写入前端页面数据, 可以分多次写入
    resp.end();
});
server.listen(3000);

接受GET参数

const http = require('http');
const url = require('url');

let server = http.createServer((req, resp) => {
    //console.log(req);
    let {pathname, query} = url.parse(req.url, true);  // true表示自动使用queryString解析
    console.log(pathname);  // 请求的url地址
    console.log(query);  // 所有的get参数
});
server.listen(3000);

接受POST参数

POST提交的数据-body(<=2GB), 无法一次性全部提交因此是分多次的提交的, 每次提交一个chunk(Buffer类型)习惯做法是建立一个数组, 把所有的buffer都接受, 然后再合并到一个Buffer中.

const http = require('http');

let server = http.createServer((req, resp) => {
    pathname = req.url;  // 请求的路径
    let arr = [];
    req.on('data',buffer=>{
        arr.push(buffer);
    });
    req.on('end',()=>{
        let result = Buffer.concat(arr);
        console.log(pathname,result.toString()); // 只有字符串是可以用toString的, 如果是文件就不要使用.
    });
});
server.listen(3000);

同时解析POST和GET

const http = require('http');
const url = require('url');
const querystring = require('querystring');
let server = http.createServer((req, resp) => {
    let path="",get_param={},post_param={}; // 定义需要的参数容器
    if(req.method=="GET"){
        let {path, get_param} = url.parse(req.url, true); 
        complete();
    }else if(req.method=="POST"){
        path = req.url;
        let arr = [];
        req.on('data',buffer=>{
            arr.push(buffer);
        });
        req.on('end',()=>{
            let result = Buffer.concat(arr);
            post_param = querystring.parse(result.toString());
            complete();
        });
    }
    function complete(){
        console.log(path, get_param, post_param);
        // 处理请求信息...
    }
});

常用第三方包

WebSocket

是一种h5下的新的的通信协议, 实现了浏览器与服务器之间的全双工通信.可以节省服务器带宽和资源(不用像http那样频繁的连接,通信,断开), 本质是基于TCP的通信.

socket.io

该包封装websocket的node.js实现, 方便使用

cnpm i socket.io -D

websocket建立方法:

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

//1.建立普通http(前端页面首先访问socket.io.js)
let server=http.createServer((req, res)=>{});
server.listen(8080);

//2.建立ws
let wsServer=io.listen(server);
wsServer.on('connection', sock=>{
    //sock.emit('name', 数据)
    //sock.on('name', function (数据){});

    sock.on('aaa', function (a, b){
      console.log(a, b, a+b);
    });
});

前端页面:

<!-- 请求后端的socket.io.js -->
<script src="http://localhost:8080/socket.io/socket.io.js" charset="utf-8"></script>
<script>
    let sock = io.connect('ws://localhost:8080/');  // socket连接ws
    sock.on('timer',time=>{
        console.log(time);
    })
</script>

常用方法

  • sock.on('name',(data)=>{}) 用于接受新的数据
  • sock.emit('name',data) 用于发送数据

mysql

纯异步回调写法:

cnpm i mysql -D

const mysql = require("mysql");

let db = mysql.createPool({  // 创建爱你连接池
    host: '192.168.40.20',
    port: 3306,
    user: 'root',
    password:'sys963-+',
    database: 'forNodeJs'
});  
db.query("SELECT * from tb_user", (err,results,fields)=>{
    if(err) throw err;
    console.log(results);
    // console.log(fields); 每一列的信息.
})

await简化版

cnpm i co co-mysql -D

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

let pool = mysql.createPool({
    host: '192.168.40.20',
    port: 3306,
    user: 'root',
    password:'sys963-+',
    database: 'forNodeJs'
});

let db = co_mysql(pool);  //  使用co_mysql包装pool

(async ()=>{
    let data = await db.query("select * from tb_user");  // 此时db.query是一个promise对象
    // 使用await可以异步获取数据. 但是await必须在一个asysn函数中.因此声明在一个async function
    console.log(data);
})();

await-fs

对应fs的await版本, 无需写大量的回调https://www.npmjs.com/package/await-fs

Koa

应用

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

也可以使用app.callback(), 配合http.createServer处理请求

const http = require('http');
const https = require('https');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
https.createServer(app.callback()).listen(3001);

常用的方法和属性:

  • app.keys=: 用于给cookie签名用的密钥
  • app.listen(port)

上下文

Koa Context 将 node 的 requestresponse 对象封装到单个对象中,为编写 Web 应用程序和 API 提供了许多有用的方法.

每个请求都将创建一个 Context,并在中间件中作为接收器引用,或者 ctx 标识符

app.use(async ctx => {
  ctx; // 这是 Context
  ctx.request; // 这是 koa Request
  ctx.response; // 这是 koa Response
});

常用属性:

  • ctx.state: 推荐的命名空间,用于通过中间件传递信息和你的前端视图(例如:ctx.state.user = await User.find(id);)
  • ctx.throw([status], [msg], [properties]): 抛出错误信息, status是状态码, msg是消息, properties是对象(一般好像没啥用)
  • ctx.cookie:
    • ctx.cookies.set(name, value, [options]): options常用设置: maxAge(毫秒), signed(true), expires(过期的Date), path(路径, 默认"/")和domain(域名), secure(https就是true), overwrite(默认false)
    • ctx.cookies.get(name, [options])

请求(request)

常用属性:

属性(=表示可写) 说明
request.header(=) 请求头
request.method(=) 请求方法
request.url(=) 请求的url
request.originalUrl 请求原始URL
request.origin 获取URL的来源,包括 protocolhost
request.href 获取完整的请求URL,包括 protocolhosturl
request.path(=) 请求路径名
request.querystring(=) GET参数
request.type 请求 Content-Type 不含参数 "charset"
request.charset
request.query(=) GET请求查询字符串
request.ip 发起请求的客户端的IP

响应(response)

属性(基本都是可写)和方法 说明
response.header 响应头
response.status 响应http状态码
response.message 一般和status关联
response.body 响应体
response.set(field, value) 设置响应标头 fieldvalue
response.append(field, value) 追加响应头
response.type 响应的Content-Type
response.redirect(url, [alt]) 重定向

常用中间件

路由koa-router

const koa = require('koa');
const Router = require('koa-router');

let server = new koa();
let router = new Router();  // 创建路由
router.get("/a", async ctx => {
    ctx.body = 'aaa';
    ctx.body += "你好";
});
server.use(router.routes());  // 服务器使用路由

// ==============================================
// 路由嵌套
let userRouter = new Router(); // 用户根Router

let adminRouter = new Router(); // 管理员Router
adminRouter.get('/a', async ctx => {
    ctx.body = "这是管理员的a";
});
let staffRouter = new Router(); // 员工Router
staffRouter.get("/a", async ctx => {
    ctx.body = "这是员工的a";
});

userRouter.use('/admin', adminRouter.routes()); // 添加路由URL前缀给admin
userRouter.use('/staff', staffRouter.routes()); // 添加路由URL前缀给staff

路由还可以做权限控制的中间件和处理异常的中间件, route支持正则路由, 以及参数匹配('/users/:id')

let adminRouter = new Router(); // 管理员router

adminRouter.get("/login", async ctx=>{
    // .. 渲染登录页面
});
adminRouter.post("/post", async ctx=>{
    // .. 处理管理员登录逻辑
});
// 访问其他需要管理员登录权限的页面的中间件
adminRouter.use("*", async (ctx, next)=>{
    if(!ctx.session['user']){
        //用户没有登录
        ctx.redirect("/login"); // 跳转到登录, 可以添加一些提示信息
    }else{
        try{
            await next(); // 放行
        }catch(e){
            // 之前可以先用日志文件记录e
            ctx.throw(500,'Internal Server Error');
        }
    }
});

// ... 需要管理员登录权限访问路由 (koa路由匹配的规则是先遇到哪个合适的就走哪个)

Session操作koa-session

const session = require('koa-session');

app.use(session({
    maxage: 20 * 60 * 1000,  // 毫秒
    renew: true  // 当session过期时自动更新session
}, app));

app.use(ctx=>{
    ctx.session.XXX = XXX;  // 即可设置session
})

静态文件请求koa-static

const static = require("koa-static");
router.all(/((\.jpg)|(\.png)|(\.gif))$/i, static('./static', {
    maxage: 30 * 86400 * 1000
}));

参数:

  • root: 静态资源所在路径(目录)
  • opts: (常用)
    • maxage 缓存时间(毫秒)
    • gzip defaults to true

koa-better-body

自动解析post body, 支持form-data, json, 和文件上传的包

https://www.npmjs.com/package/koa-better-body

文档里面说了, 所有的参数都是直接传递给formidable的, 因此formidable的参数也是支持的. 可以限制文件的大小什么..

http://www.ptbird.cn/koa-body.html#menu_index_7

const Koa = require('koa');
const Router = require('koa-router');
const betterbody = require('koa-better-body');
const path = require("path");


let app = new Koa();

let router = new Router();

app.use(betterbody({
    uploadDir: path.resolve(__dirname,'./upload'),
}));

router.post("/upload", async (ctx, next) => {
    console.log(ctx.request.fields);
    console.log(ctx.request.files);
    ctx.body = "OK";
});

app.use(router.routes());
app.listen(8080);

koa-art-template

https://aui.github.io/art-template/zh-cn/docs/

npm install --save art-template
npm install --save koa-art-template

配置:

const Koa = require('koa');
const render = require('koa-art-template');

const app = new Koa();
render(app, {
  root: path.join(__dirname, 'view'),  // 模板路径
  extname: '.art',   // 模板后缀
  debug: process.env.NODE_ENV !== 'production'  // debug模式, 开发时直接写true
});

配合路由使用:

router.get("/login", async ctx => {
    await ctx.render('admin',{
        user:user  // 携带数据
    })
});

文件下载

https://segmentfault.com/a/1190000014056810

JavaScript
1
https://gitee.com/samuelsue/frontend_interview.git
git@gitee.com:samuelsue/frontend_interview.git
samuelsue
frontend_interview
前端面试
master

搜索帮助