Koa

参考资料

  • https://chenshenhai.github.io/koa2-note/note/static/server.html
  • https://github.com/topics/koa
Koa_第1张图片
Koa

环境部署

下载安装NodeJS

下载地址: http://nodejs.cn/download/

$ node -v
v10.15.0

$ npm -v
6.4.1

Koa2

官网:https://koa.bootcss.com/

Koa是基于Node.js平台的下一台Web开发框架,Koa是一个全新的Web框架,由Express原班人马打造,致力于成为Web应用和API开发领域中更小且更加富有表现力、更健壮的基石。通过async函数Koa帮你丢弃回调函数,并有力地增强错误处理。Koa并没有绑定任何中间件,而是提供了一套优雅的方法帮助快速编写服务器端应用程序。

Koa2相比较Koa1最大区别在于中间件的写法,Koa1使用Generator,Koa2使用async/await语法,因此Node.js必须大于v7.6.0+。

安装

Koa依赖Node v7.6.0 或ES2015+ 和 async方法支持。

创建工程文件夹并进入,使用npm初始化项目。

# 手工创建项目
$ mkdir project && cd  project

# 快速生成package.json文件
$ npm init -y

$ vim package.json
{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"node app.js" // 添加快捷启动命令
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
  }
}

运行脚本

可直接使用node app.js运行脚本,也可以使用它的快捷方式npm start运行app.js脚本。

$ node app.js
$ npm start

安装Koa

$ npm install koa -S
$ npm i koa

应用程序

Koa应用程序是一个包含一组中间件函数的对象,它按照类似堆栈的方式组织和执行。Koa类似中间件系统。

$ vim app.js

导入Koa,在Koa2中由于导入的是一个类,所以使用大写的Koa。

const Koa = require("koa");

创建Koa对象,即Web应用本身app

const app = new Koa();

对于任何HTTP请求,app将调用异步函数进行处理。

app.use(async (ctx, next)=>{
  await next();
  // 设置HTTP响应的内容类型
  ctx.response.type = "text/html";
  // 设置HTTP响应的内容
  ctx.response.body = "hello world";
});

每当Koa收到一个HTTP请求时,会调用通过app.use()注册的async异步函数并传入ctxnext参数。可以针对ctx进行操作并设置返回内容。

async标记的函数称为异步函数,使用await调用另一个异步函数,async/await关键字是在ES7中引入的。

ctx是Koa提供的Context对象,封装了requestresponse对象,每次HTTP Request都会创建一个Context上下文对象。

ctx是由Koa传入的封装了requestresponse的变量,可通过ctx.requestctx.response访问请求和响应。

中间件

next是Koa传入将要处理的下一个异步函数,await next();表示处理下一个异步函数,然后再设置response响应的Content-Typebody内容。

await next();有什么作用呢?

Koa将多个async异步函数组成了一个处理链,每个async异步函数都可以做自己的事情,然后使用await next()来调用下一个async异步函数。这里将每个async异步函数成为中间件middleware,这些中间件可以组合起来完成很多实用的功能。

监听3000端口

app.listen(3000);

浏览器访问:http://127.0.0.1:3000

JS异步发展史

  • ES5:回调函数callback
  • ES6:Promise对象和Generator函数
  • ES7:async/await语法

async/await

async用于声明一个函数是异步的,await只能出现在async修改的函数中。async函数会返回一个promise对象,如果在async函数返回一个直接量它最终将通过Promise.resolve封装成promise对象,进而可以直接通过promise对象的then方法来获取这个直接量。

await会暂停当前async的执行,await会阻塞代码的执行直到await后的表达式处理完毕,代码才继续往下执行。await后的表达式可以是一个promise对象也可以任何需要等待的值。如果await等到的是一个promise对象,await就会阻塞后续代码直到promise对象resolve后得到resolve的值作为await表达式的运算结果。

async/await只是一种语法糖,其代码执行与回调函数嵌套是本质上是没有区别的,只是写法上让人以同步的思维去思考,避开回调地狱。简而言之,async/await是以同步的思维去编写异步的代码,所以async/await并不会影响Node.js的并发数。

中间件

中间件类似于过滤器,用于在客户端和应用程序之间处理请求和响应的方法。中间件的执行类似剥洋葱,但并非一层层的执行,而是以next为分界,先执行本层next之前的部分,当下一层中间件执行完毕后再执行本层next之后的部分。

Koa_第2张图片
中间件

中间件是为了解决复杂应用中频繁回调而设计的级联式代码,它并不直接将控制权完全交给下一个中间件,而是碰到next后去下一个中间件,等到下面都执行完毕后在执行next后续代码。

例如:使用三个中间件组成处理链,依次打印日志,记录处理时间,输出HTML。

//中间件处理链
app.use(async (ctx, next) => {
    console.log(`${ctx.request.method} ${ctx.request.url}`);
    await next();//调用下一个中间件
});
app.use(async (ctx, next) => {
    const begin_time = new Date().getTime();
    await next();//处理下一个中间件
    const spend_ms = new Date().getTime() - begin_time;//耗费时间
    console.log(`Time: ${spend_ms}ms`);
});
app.use(async (ctx, next) => {
    await next();
    ctx.response.type = "text/html";
    ctx.response.body = "request received";
});

注意中间件的顺序也就是调用app.use()的顺序将决定了中间件的执行顺序。如果某个中间件没有调用await next()则后续中间件将不再执行。

例如:检测用户权限的中间件可以决定是否继续处理请求,若不则直接返回403错误。

app.use(async (ctx, next) => {
    if(await checkAuth(ctx)){
        await next();
    }else{
        ctx.response.status = 403;
    }
});

简单来说,理解了中间件也就学会使用Koa了。

获取GET请求数据

Koa2中GET请求可通过ctx.request接收,接收方式分为两种:

  • ctx.request.query 获取格式化后的参数对象
  • ctx.request.querystring 获取请求字符串
  • ctx.query
  • ctx.querystring

例如:

app.use(async (ctx, next) => {
    const url = ctx.url;
    //使用ctx.request接收
    const rq = ctx.request;
    const rq_query = rq.query;
    const rq_qs = rq.querystring;
    //使用ctx接收
    const ctx_query = ctx.query;
    const ctx_qs = ctx.querystring;

    //返回
    body = {};
    body.rq_query = rq_query;
    body.rq_qs = rq_qs;
    body.ctx_query = ctx_query;
    body.ctx_qs = ctx_qs;
    ctx.body = body;
});

获取POST请求数据

Koa2中没有对POST请求的处理封装获取参数的方法,需要通过解析上下文ctx中的元素来获取,具体可分为三步:

  1. 解析上下文ctx对象中的原生Node.js对象req
  2. 将POST表单数据解析为querystring查询字符串
  3. 将查询字符串转换为JSON格式
const Koa = require("koa");
const app = new Koa();

const parseQueryString = (querystring) => {
    const queryData = {};
    const qsList = querystring.split("&");
    for(let [index, qs] of qsList.entries()){
        let kvList = qs.split("=");
        queryData[kvList[0]] = decodeURIComponent(kvList[1]);
    }
    return queryData;
};

const parsePostData = (ctx) => {
    return new Promise((resolve, reject) => {
        try{
            let postData = "";
            ctx.req.on("data", (data)=>{
                postData += data;
            })
            ctx.req.addListener("end", ()=>{
                let parseData = parseQueryString(postData);
                resolve(parseData);
            });
        }catch(error){
            reject(error);
        }
    });
};

app.use(async(ctx, next) => {
    if(ctx.method === "POST"){
        let postData = await parsePostData(ctx);
        ctx.body = postData;
    }
});

app.listen(3000, ()=>{
    console.log("server is running");
});

另一种方式是使用koa-bodyparser中间件,对于POST请求的处理,koa-bodyparser中间件可以将Koa上下文中的formData数据解析到ctx.request.body中。

koa-bodyparser

安装

$ npm i koa-bodyparser -S

使用

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

const bodyParser = require("koa-bodyparser");
app.use(bodyParser());

app.use(async(ctx, next) => {
    if(ctx.method === "POST"){
        ctx.body = ctx.request.body;
    }
});

app.listen(3000, ()=>{
    console.log("server is running");
});

supervisor

使用supervisor自动重启模块

$ npm i supervisor -g
# 修改package.json,设置scripts选项下的start。
"scripts":
{
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"supervisor app.js" //设置npm start启动项
}

koa-router

koa-router 路由组件

$ npm i koa-router -S
var Koa = require("koa");
var app = new Koa();
var router = require("koa-router")();

router.get("/", (ctx, next) => {
  console.log("homepage");
});

app.use(router.routes()).use(router.allowedMethods());

参考资料

  • https://www.npmjs.com/package/koa-router

koa-router是Koa的路由组件,路由的功能是指定具体的访问路径,通过访问路径指向特定的功能模块。

安装

# 安装Koa
$ npm install koa --save

# 安装koa-router
$ npm install koa-router --save

使用

var Koa = require("koa");
var Router = require("koa-router");

var app = new Koa();
var router = new Router();

app.use(router.routes()).use(router.allowedMethods());

router.get("/", (ctx, next)=>{

});

koa-simple-router

路由koa-simple-router

$ npm i koa-simple-router -S

koa-cors 跨域组件

  • 参考资料 https://github.com/zadzbw/koa2-cors

安装

$ npm install --save koa2-cors

使用

var Koa = require('koa');
var cors = require('koa2-cors');

var app = new Koa();
app.use(cors());

koa-static

koa-static为原生koa2实现静态资源服务器

一个HTTP请求访问Web服务静态资源,一般响应结果有3种情况:

  • 访问文本,如css、js、image...
  • 访问静态目录
  • 找不到资源则抛出404错误

为Koa2实现静态资源加载的服务,用于访问css/js/img等静态资源,若访问图片则返回二进制,其他文件则直接输出字符串。

$ npm i koa-static -S
# 设置static目录用于存储静态资源,app.js添加中间件。
app.use(require("koa-static")(__dirname + "/static"));

koa-views

koa-views为Koa2加载的模板引擎

$  npm i koa-views -S

根目录下创建views目录用于存储视图模板文件,并在app.js文件中添加中间件配置。

//模板引擎
app.use(require("koa-views")(__dirname+"/views"));

koa-logger

//日志配置
app.use(require("koa-logger")());

koa-bodyparser

$ npm i koa-bodyparser@2 -S
app.use(require("koa-bodyparser")())

koa-session

$ npm i koa-session -S

mongoose

https://mongoosejs.com

$ npm i mongoose -S

config


$ npm i config -S

mysql

mysql模块是node操作MySQL的引擎,可在node.js环境下对MySQL数据库进行CURD等操作。

$ npm i mysql -S

你可能感兴趣的:(Koa)