2023-03-28

2023-03-27  本文已影响0人  Asagi浅木

一、koa2 快速开始

1、环境准备

因为node.js v7.6.0开始完全支持async/await,不需要加flag,所以node.js环境都要7.6.0以上 node.js环境 版本v7.6以上 npm 版本3.x以上

2、快速开始

2.1 安装koa2

# 初始化package.jsonnpm init# 安装koa2 npm install koa

2.2 hello world 代码

constKoa=require('koa')constapp=newKoa()app.use(async(ctx)=>{ctx.body='hello koa2'})app.listen(3000)console.log('[demo] start-quick is starting at port 3000')

2.3 启动demo

由于koa2是基于async/await操作中间件,目前node.js 7.x的harmony模式下才能使用,所以启动的时的脚本如下:

node index.js

二、async/await使用

1、快速上手理解

先复制以下这段代码,在粘贴在chrome的控制台console中,按回车键执行

functiongetSyncTime(){returnnewPromise((resolve,reject)=>{try{letstartTime=newDate().getTime()setTimeout(()=>{letendTime=newDate().getTime()letdata=endTime-startTimeresolve(data)},500)}catch(err){reject(err)}})}asyncfunctiongetSyncData(){lettime=awaitgetSyncTime()letdata=`endTime - startTime = ${time}`returndata}asyncfunctiongetData(){letdata=awaitgetSyncData()console.log(data)}getData()

2、从上述例子可以看出 async/await 的特点:

可以让异步逻辑用同步写法实现

最底层的await返回需要是Promise对象

可以通过多层 async function 的同步写法代替传统的callback嵌套

三、koa2简析结构

1、源码文件

├── lib │ ├── application.js │ ├── context.js │ ├── request.js │ └── response.js └── package.json

这个就是 GitHubhttps://github.com/koajs/koa上开源的koa2源码的源文件结构,核心代码就是lib目录下的四个文件

application.js 是整个koa2 的入口文件,封装了context,request,response,以及最核心的中间件处理流程。

context.js 处理应用上下文,里面直接封装部分request.js和response.js的方法

request.js 处理http请求

response.js 处理http响应

2、koa2特性

只提供封装好http上下文、请求、响应,以及基于async/await的中间件容器。

利用ES7的async/await的来处理传统回调嵌套问题和代替koa@1的generator,但是需要在node.js 7.x的harmony模式下才能支持async/await。

中间件只支持 async/await 封装的,如果要使用koa@1基于generator中间件,需要通过中间件koa-convert封装一下才能使用。

四、koa中间件开发和使用

koa v1和v2中使用到的中间件的开发和使用

generator 中间件开发在koa v1和v2中使用

async await 中间件开发和只能在koa v2中使用

1、generator中间件开发

1.1 generator中间件开发

generator中间件返回的应该是function * () 函数

/* ./middleware/logger-generator.js */functionlog(ctx){console.log(ctx.method,ctx.header.host+ctx.url)}module.exports=function(){returnfunction*(next){// 执行中间件的操作log(this)if(next){yieldnext}}}

1.2 generator中间件在koa@1中的使用

generator 中间件在koa v1中可以直接use使用

constkoa=require('koa')// koa v1constloggerGenerator=require('./middleware/logger-generator')constapp=koa()app.use(loggerGenerator())app.use(function*(){this.body='hello world!'})app.listen(3000)console.log('the server is starting at port 3000')

1.3 generator中间件在koa@2中的使用

generator 中间件在koa v2中需要用koa-convert封装一下才能使用

constKoa=require('koa')// koa v2constconvert=require('koa-convert')constloggerGenerator=require('./middleware/logger-generator')constapp=newKoa()app.use(convert(loggerGenerator()))app.use((ctx)=>{ctx.body='hello world!'})app.listen(3000)console.log('the server is starting at port 3000')

2、async中间件开发

2.1 async 中间件开发

/* ./middleware/logger-async.js */functionlog(ctx){console.log(ctx.method,ctx.header.host+ctx.url)}module.exports=function(){returnasyncfunction(ctx,next){log(ctx);awaitnext()}}

2.2 async 中间件在koa@2中使用

async 中间件只能在 koa v2中使用

constKoa=require('koa')// koa v2constloggerAsync=require('./middleware/logger-async')constapp=newKoa()app.use(loggerAsync())app.use((ctx)=>{ctx.body='hello world!'})app.listen(3000)console.log('the server is starting at port 3000')

Ⅱ、路由

一、koa2 原生路由实现

1、简单例子

constKoa=require('koa')constapp=newKoa()app.use(async(ctx)=>{leturl=ctx.request.url  ctx.body=url})app.listen(3000)

访问http://localhost:3000/hello/world页面会输出 /hello/world,也就是说上下文的请求request对象中url之就是当前访问的路径名称,可以根据ctx.request.url 通过一定的判断或者正则匹配就可以定制出所需要的路由。

2、定制化的路由

demo源码

https://github.com/ChenShenhai/koa2-note/tree/master/demo/route-simple

2.1 源码文件目录

.├── index.js├── package.json└── view    ├── 404.html    ├── index.html    └── todo.html

2.2 demo源码

constKoa=require('koa')constfs=require('fs')constapp=newKoa()/**

* 用Promise封装异步读取文件方法

* @param  {string} page html文件名称

* @return {promise}     

*/functionrender(page){returnnewPromise((resolve,reject)=>{letviewUrl=`./view/${page}`fs.readFile(viewUrl,"binary",(err,data)=>{if(err){reject(err)}else{resolve(data)}})})}/**

* 根据URL获取HTML内容

* @param  {string} url koa2上下文的url,ctx.url

* @return {string}    获取HTML文件内容

*/asyncfunctionroute(url){letview='404.html'switch(url){case'/':view='index.html'breakcase'/index':view='index.html'breakcase'/todo':view='todo.html'breakcase'/404':view='404.html'breakdefault:break}lethtml=awaitrender(view)returnhtml}app.use(async(ctx)=>{leturl=ctx.request.urllethtml=awaitroute(url)ctx.body=html})app.listen(3000)console.log('[demo] route-simple is starting at port 3000')

2.3 运行demo

执行运行脚本

node -harmony index.js

二、koa-router中间件

如果依靠ctx.request.url去手动处理路由,将会写很多处理代码,这时候就需要对应的路由的中间件对路由进行控制,这里介绍一个比较好用的路由中间件koa-router

1、安装koa-router中间件

# koa2 对应的版本是 7.xnpm install --save koa-router@7

2、快速使用koa-router

constKoa=require('koa')constfs=require('fs')constapp=newKoa()constRouter=require('koa-router')lethome=newRouter()// 子路由1home.get('/',async(ctx)=>{lethtml=`    <ul>

      <li><a href="/page/helloworld">/page/helloworld</a></li>

      <li><a href="/page/404">/page/404</a></li>

    </ul>

  `ctx.body=html})// 子路由2letpage=newRouter()page.get('/404',async(ctx)=>{ctx.body='404 page!'}).get('/helloworld',async(ctx)=>{ctx.body='helloworld page!'})// 装载所有子路由letrouter=newRouter()router.use('/',home.routes(),home.allowedMethods())router.use('/page',page.routes(),page.allowedMethods())// 加载路由中间件app.use(router.routes()).use(router.allowedMethods())app.listen(3000,()=>{console.log('[demo] route-use-middleware is starting at port 3000')})

Ⅲ、请求数据获取

一、GET请求数据获取

1、使用方法

在koa中,获取GET请求数据源头是koa中request对象中的query方法或querystring方法,query返回是格式化好的参数对象,querystring返回的是请求字符串,由于ctx对request的API有直接引用的方式,所以获取GET请求数据有两个途径。

是从上下文中直接获取 请求对象ctx.query,返回如 { a:1, b:2 } 请求字符串 ctx.querystring,返回如 a=1&b=2

是从上下文的request对象中获取 请求对象ctx.request.query,返回如 { a:1, b:2 } 请求字符串 ctx.request.querystring,返回如 a=1&b=2

2、举个例子

2.1 例子代码

constKoa=require('koa')constapp=newKoa()app.use(async(ctx)=>{leturl=ctx.url// 从上下文的request对象中获取letrequest=ctx.requestletreq_query=request.queryletreq_querystring=request.querystring// 从上下文中直接获取letctx_query=ctx.queryletctx_querystring=ctx.querystring  ctx.body={url,req_query,req_querystring,ctx_query,ctx_querystring}})app.listen(3000,()=>{console.log('[demo] request get is starting at port 3000')})

2.2 执行程序

node get.js

二、POST请求参数获取

1、原理

对于POST请求的处理,koa2没有封装获取参数的方法,需要通过解析上下文context中的原生node.js请求对象req,将POST表单数据解析成query string(例如:a=1&b=2&c=3),再将query string 解析成JSON格式(例如:{"a":"1", "b":"2", "c":"3"})

注意:ctx.request是context经过封装的请求对象,ctx.req是context提供的node.js原生HTTP请求对象,同理ctx.response是context经过封装的响应对象,ctx.res是context提供的node.js原生HTTP请求对象。

解析出POST请求上下文中的表单数据

// 解析上下文里node原生请求的POST参数functionparsePostData(ctx){returnnewPromise((resolve,reject)=>{try{letpostdata="";ctx.req.addListener('data',(data)=>{postdata+=data})ctx.req.addListener("end",function(){letparseData=parseQueryStr(postdata)resolve(parseData)})}catch(err){reject(err)}})}// 将POST请求参数字符串解析成JSONfunctionparseQueryStr(queryStr){letqueryData={}letqueryStrList=queryStr.split('&')console.log(queryStrList)for(let[index,queryStr]ofqueryStrList.entries()){letitemList=queryStr.split('=')queryData[itemList[0]]=decodeURIComponent(itemList[1])}returnqueryData}

2、举个例子

2.1 例子代码

constKoa=require('koa')constapp=newKoa()app.use(async(ctx)=>{if(ctx.url==='/'&&ctx.method==='GET'){// 当GET请求时候返回表单页面lethtml=`      <h1>koa2 request post demo</h1>

      <form method="POST" action="/">

        <p>userName</p>

        <input name="userName" /><br/>

        <p>nickName</p>

        <input name="nickName" /><br/>

        <p>email</p>

        <input name="email" /><br/>

        <button type="submit">submit</button>

      </form>

    `ctx.body=html}elseif(ctx.url==='/'&&ctx.method==='POST'){// 当POST请求的时候,解析POST表单里的数据,并显示出来letpostData=awaitparsePostData(ctx)ctx.body=postData}else{// 其他请求显示404ctx.body='<h1>404!!! o(╯□╰)o</h1>'}})// 解析上下文里node原生请求的POST参数functionparsePostData(ctx){returnnewPromise((resolve,reject)=>{try{letpostdata="";ctx.req.addListener('data',(data)=>{postdata+=data})ctx.req.addListener("end",function(){letparseData=parseQueryStr(postdata)resolve(parseData)})}catch(err){reject(err)}})}// 将POST请求参数字符串解析成JSONfunctionparseQueryStr(queryStr){letqueryData={}letqueryStrList=queryStr.split('&')console.log(queryStrList)for(let[index,queryStr]ofqueryStrList.entries()){letitemList=queryStr.split('=')queryData[itemList[0]]=decodeURIComponent(itemList[1])}returnqueryData}app.listen(3000,()=>{console.log('[demo] request post is starting at port 3000')})

2.2 启动例子

node post.js

三、koa-bodyparser中间件

1、原理

对于POST请求的处理,koa-bodyparser中间件可以把koa2上下文的formData数据解析到ctx.request.body中

安装koa2版本的koa-bodyparser@3中间件

npm install --save koa-bodyparser@3

2、举个例子

2.1 例子代码

constKoa=require('koa')constapp=newKoa()constbodyParser=require('koa-bodyparser')// 使用ctx.body解析中间件app.use(bodyParser())app.use(async(ctx)=>{if(ctx.url==='/'&&ctx.method==='GET'){// 当GET请求时候返回表单页面lethtml=`      <h1>koa2 request post demo</h1>

      <form method="POST" action="/">

        <p>userName</p>

        <input name="userName" /><br/>

        <p>nickName</p>

        <input name="nickName" /><br/>

        <p>email</p>

        <input name="email" /><br/>

        <button type="submit">submit</button>

      </form>

    `ctx.body=html}elseif(ctx.url==='/'&&ctx.method==='POST'){// 当POST请求的时候,中间件koa-bodyparser解析POST表单里的数据,并显示出来letpostData=ctx.request.body    ctx.body=postData}else{// 其他请求显示404ctx.body='<h1>404!!! o(╯□╰)o</h1>'}})app.listen(3000,()=>{console.log('[demo] request post is starting at port 3000')})

2.2 启动例子

node post-middleware.js

Ⅳ、静态资源加载

koa-static中间件使用

1、使用例子

constKoa=require('koa')constpath=require('path')conststatic=require('koa-static')constapp=newKoa()// 静态资源目录对于相对入口文件index.js的路径conststaticPath='./static'app.use(static(path.join(__dirname,staticPath)))app.use(async(ctx)=>{ctx.body='hello world'})app.listen(3000,()=>{console.log('[demo] static-use-middleware is starting at port 3000')})

Ⅴ、模板引擎

koa2加载模板引擎

1、快速开始

1.1 安装模块

# 安装koa模板使用中间件npm install --save koa-views# 安装ejs模板引擎npm install --save ejs

1.2 使用模板引擎

文件目录

├── package.json├── index.js└── view    └── index.ejs

./index.js文件

constKoa=require('koa')constviews=require('koa-views')constpath=require('path')constapp=newKoa()// 加载模板引擎app.use(views(path.join(__dirname,'./view'),{extension:'ejs'}))app.use(async(ctx)=>{lettitle='hello koa2'awaitctx.render('index',{title,})})app.listen(3000)

./view/index.ejs 模板

<!DOCTYPE html><html><head><title><%= title %></title></head><body><h1><%= title %></h1><p>EJS Welcome to <%= title %></p></body></html>

0人点赞

NodeJS

作者:硅谷干货

链接:https://www.jianshu.com/p/920ad3e248ec

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

上一篇下一篇

猜你喜欢

热点阅读