koa框架和mongodb数据库,一小时快速入门和直击实战详细解读,建议收藏

Posted 贪吃ღ大魔王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了koa框架和mongodb数据库,一小时快速入门和直击实战详细解读,建议收藏相关的知识,希望对你有一定的参考价值。

koa

要求:nodejs的版本要高于7.6,因为 Node.js 7.6 版本 开始完全支持 async/await,所以才能完全支持我们的 Koa

npm i koa -S

使用

const Koa = require('koa');
const app = new Koa();
// ctx是上下文,其中包含了request和response
app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

注意:在koa中的app引用,只有use方法可以用来处理路由,没有请求动词方法,例如:app.get()这样会报错。

async/await和promise的使用

async用于修饰函数,放在函数声明的前面,将其后的函数的返回值封装成一个 Promise 对象

例:在终端中执行以下代码

async function testAsync(){
    return 'Hello async';
};
const result = testAsync();
console.log(result); // Promise { 'Hello async' }

await必须在async方法中才可以使用,表示等待。等待的只是一个表达式,官方文档中说的是promise对象,其实他也可以接收普通的值。如果这个普通的值是一个函数的话,就等待这个函数的返回值。

例:

function getData() {
    return 'This is data';
};
async function testAsync() {
    return 'Hello async';
};
async function test() {
    // await 返回普通值
    const v1 = await getData();
    console.log(v1);
    // This is data
 
    // await 返回promise对象
    const v2 = await testAsync();
    console.log(v2);
    // Hello async
};
test();

路由

koa中要处理路由就需要使用路由模块来处理:

npm i koa-router -S

路由使用:

const Koa = require('koa')
const koaRouter = require('koa-router') // 导入路由
const router = new koaRouter() // 实例化路由
const app = new Koa()
router.get('/',(ctx,next)=>{
    ctx.body = "hello"
})

router.get('/news',(ctx,next)=>{
    ctx.body = '新闻页面'
})

app.use(router.routes()) // 启动路由 - 让路由生效
app.use(router.allowedMethods()) // 如果之前的没有设置响应头,配置此选项以后可以自动设置响应头 - 可加可不加(错误的时候会自动响应响应头)

app.listen(3000)

其中的导入路由和实例化路由可以合成一行:

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

路由处理中回调函数的next表示,让这个路由继续向下匹配处理。

路由执行顺序遵循洋葱圈模型:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rL2cRDeK-1625882327725)(media/1624684612952.png)]

例:

ar Koa = require('koa');
var router = require('koa-router')();
var app = new Koa();
 
app.use(async (ctx, next) => {
    console.log('1.这是一个中间件01');
    await next();
    console.log('5.匹配完路由以后又会返回来执行中间件')
});
app.use(async (ctx, next) => {
    console.log('2.这是一个中间件02');
    await next();
    console.log('4.匹配完路由以后又会返回来执行中间件')
});                   
router.get('/news', async (ctx) => {
    console.log('3.匹配到了news这个路由');
    ctx.body = '新闻页'
});
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);

在这里插入图片描述

koa中的上下文ctx

koa中的ctx,包含了所有请求和所有的响应:

  • ctx.request - 代表服务器中的request对象

  • ctx.req - 代表服务器中的request对象 - ctx.request的简写

  • ctx.response - 代表服务器中的response对象

  • ctx.res - 代表服务器中的response对象 - ctx.reponse的简写

  • ctx.cookies.get(cookie的name) - 获取cookie

  • ctx.cookies.set(name, value, [options]) - 设置cookie

    其中的option选项:

    • maxAge:毫秒数 - 有效期 - 表示多长时间之后失效
    • expires:有效期
    • path:路径
    • domain:指定子域名下可以访问
    • secure:设置为true的时候,表示只有https才能访问
    • httpOnly:true表示只能服务器端能访问,false表示客户端和服务器都能访问

请求信息

koa中默认将请求的信息ctx.request上的内容绑定在了ctx上

  • ctx.headers - 获取请求头信息
  • ctx.header - 获取请求头信息 - ctx.headers的简写 - 可设置
  • ctx.method - 获取请求方法 - 可设置
  • ctx.url - 获取请求路径 - 带?的参数 - 可设置
  • ctx.path - 获取请求路径 - 不带?的参数
  • ctx.query - 获取?后的参数 - 结果为对象
  • ctx.querystring - 获取?后的擦书 - 结果是字符串
  • ctx.ip - 获取请求ip

响应信息

在koa中,将响应对象ctx.reponse绑定在了ctx上:

  • ctx.body - 响应主体 - 可赋值 - 可以是任意数据类型 - 参考官方文档
  • ctx.status - 响应状态码 - 可赋值 - 必须是数字
  • ctx.message - 响应状态描述 - 可赋值 - 设置状态描述 - 不能是中文
  • ctx.redirect() - 跳转路由

有些响应必须是使用响应对象来操作:

  • response.set(fields) - 设置多个响应头

    ctx.set({
      'Etag': '1234',
      'Last-Modified': date
    });
    
  • response.append(field, value) - 追加一个响应头

    ctx.append('Link', '<http://127.0.0.1/>');
    
  • response.set(field, value) - 设置一个响应头

    ctx.set('Cache-Control', 'no-cache');
    
  • response.has(field) - 判断是否包含了某个响应头 - 返回布尔值

    let bool = ctx.response.has('X-RateLimit-Limit');
    
  • response.get(field) - 获取响应头

    const etag = ctx.response.get('ETag');
    

中间件

中间件可以理解为一个过滤器,让路由通过一个过滤器之后,进行或终止后续的处理。

中间件的作用:

执行任何代码

修改请求和响应对象

终结请求 - 响应循环

调用堆栈中的下一个中间件

正常情况下对于路由的处理,经过一个处理的回调函数之后,就停止了,如果我们希望他能继续执行下一个处理,可以调用next参数:

路由级别中间件

router.get('/goods',(ctx,next)=>{
    ctx.body = '商品';
    next() // 执行完这个处理回调之后继续向下执行 - 可以匹配下一个路由,进行进一步的处理
})
router.get('/goods',(ctx,next)=>{
    ctx.body += "页面"
})

中间件执行结束后会执行next函数下的内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VovcdYFr-1625882327732)(media/1624267908642.png)]

这是路由级别中间件。

应用级别中间件

app.use(回调函数) // 可以匹配任意路由 - 需要向下进行的话就调用next
// 例
app.use(async (ctx,next)=>{
   	console.log(new Date()) // 每个路由都会打印时间
    next()
})

应用级别中间件总是会先于路由级别中间件执行,无论放在前面或后面。

错误处理中间件

利用应用级别中间件会先执行的特性处理错误:

app.use(async (ctx,next)=>{
    console.log('这是中间件');
    await next()
    // 当next向下执行后都没有匹配到合适的路由,就判断是否是404状态码来处理错误
    if(ctx.status == 404){
        ctx.body = "404页面,未找到资源"
    }else{
        console.log(ctx.url);
    }
    console.log(ctx.status);
})

第三方中间件

app.use(router.routes())

获取get请求主体

ctx.query // 获取到所有参数键值对组成的对象
ctx.querystring // 获取到所有参数的字符串形式

获取所有请求信息:

ctx.request

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJ8iHZW4-1625882327733)(media/1624201051211.png)]

获取get参数也可以从请求信息中获取:

const req = ctx.request;
req.query // 对象
req.querystring // 字符串

动态路由参数:

router.get('/news/:id',(ctx,next)=>{
    console.log(ctx.params); 
    ctx.body = '新闻页面'
})
// 请求地址:http://localhost:3000/news/123
// 获取到的值: { id: '123' }

获取post请求主体

原生nodejs获取:

router.post('/news',async ctx=>{
    var str = '';
    ctx.req.on('data',chunk=>{
        str += chunk
    })
    crx.req.on('end',()=>{
        console.log(str) // str就是获取到数据
    })
    ctx.body = "111"
})

使用第三方插件:

npm i koa-bodyparser

使用:

const bodyParser = require('koa-bodyparser')
router.post('/news',async ctx=>{
    console.log(ctx.request.body);
    ctx.body = "111"
})
app.use(bodyParser())

静态资源托管

依赖插件:koa-static

npm i koa-static 

使用:

const staticMid = require('koa-static')
app.use(staticMid(__dirname + '静态资源目录')) // 请求的时候不需要加目录名 - 可以配置多个

静态资源托管可以配置多个,多个静态资源放在不同的文件夹时使用。

模板引擎

ejs

npm i koa-views # 让koa中能使用模板引擎
npm i ejs # 使用ejs

使用:

const views = require('koa-views')
app.use(views(模板存放目录,{
    extension:"ejs"
}))
// 此时模板的后缀要ejs
// 或者
app.use(views(模板存放目录,{
    map:{
        html:"ejs"
    }
}))
// 此时模板的后缀要html
// 渲染时 - 渲染是异步的,所以必须加await
await ctx.render(模板名称,{
    数据
})

ejs语法:

<!-- 输出数据 -->
<%=变量名%>
<!-- 输出html内容并解析 -->
<%-变量名%>
<!-- 循环 -->
<%for(var i=0;i<list.length;i++){%>
    <li><%=list[i]%></li>
<%}%>
<!-- 判断 -->
<%if(num > 18 ){%>
    成年
<%}else{%>
    未成年
<%}%>
<!-- 包含文件 -->
<%include 文件路径 %>

公共数据放在一个中间件中,然后每个响应处理都可以使用:

app.use(async (ctx,next)=>{
    ctx.state = {
        username:"张三"
    }
    await next()
})

其他响应处理就不用再次绑定数据,直接在模板中就能使用这个数据了 。

art-template

npm i art-template
npm i koa-art-template

使用:

const render = require('koa-art-template')
render(app,{
    root:path.join(__dirname,'文件夹'), // 模板引擎存放地址
    extname:".art" // 指定模板引擎后缀名
    debug:process.env.NODE_ENV !== 'production'
})

其他使用跟ejs一样了

其他模块的使用

cookie注意事项

koa中不能直接设置中文的cookie,需要先将中文转为base64字符串设置,读取的时候,再将base64的字符串转换成中文:

// 中文转base64字符串
new Buffer(中文字符串).toString('base64')
// base64字符串转中文
new Buffer(base64字符串,'base64').toString()

session

npm i koa-session

使用:

const session = require('koa-session')
// 配置session的中间件
app.keys = ['some secret hurr']
const CONFIG = {
    key: "koa:sess",
    maxAge:86400000, // 有效期 - 毫秒数
    overwrite:true, // 设置没什么效果
    httpOnly:true, // true表示只有服务器端可以获取
    signed:true, // 默认
    rolling:false, // 每次访问重新设置
    renew:true // 快到期的时候重新设置 - 一般会设置为true - true的时候会重新设置,只要操作就不会过期了
}

// 设置
ctx.session.=// 获取
console.log(ctx.session.)

上传

npm install  koa-multer --save

使用:

// 引入koa-multer
const multer = require('koa-multer');
const router = require('koa-router')();
// 配置koa-multer
var storage = multer.diskStorage({
    // 文件保存路径
    destination: function (req, file, cb) {
        // 注意路径必须存在
        cb(null, 'public/uploads')
    },
    // 修改文件名称
    filename: function (req, file, cb) {
        var fileFormat = (file.originalname).split(".");
        // 图片名称为时间戳加后辍名
        cb(null,Date.now()+"."+fileFormat[fileFormat.length-1]);
    }
});
// 加载配置
var upload = multer({ storage: storage })
// 使用上传,upload.single()代表上传单个,参数为上传input的name值
router.post('/doAdd', 
    upload.single('input-name-value'), async (ctx, next) => {
        ctx.body = {
            // 返回文件名
            filename: ctx.req.file.filename,
            body: ctx.req.body
        }
    }
)

数据库操作

mysql

mongoDB

mongodb操作:依赖mongodb

npm i mongodb

使用:

const MongoClient = require('mongodb').MongoClient;
MongoClient.connect(dbUrl,(err,client)=>{
    if(err){
    	console.log('连接错误!,错误为:'+err)
        return;
    }
    let db = client.db(数据库名称)
    let result = db.collection(表名).find({})
    result.toArray((err,docs)=>{
        console.log(docs)
    })
})

封装:

新建config.js

const config = {
    dbUrl:'mongodb://localhost:27017',
    dbName:'koa'
}

module.exports = config

新建mongo.js

class Mongo{
    static getInstance(){ // 多次实例化使用的同一个对象
		if(!Mongo._intance) Mongo._instance = new Mongo()
    	return Mongo._instance
    }
    constructor(){
        this.db = null
        this.config = require('./config.js')
        this.MongoClient = require('mongodb').MongoClient;
        this.connect()
    }
    connect(){
		return new Promise((resolve,reject)=>{
            if(!this.db){
            	this.MongoClient.connect(this.config.dbUrl,(err,client)=>{
                    if(err){
                        reject(err)
                    }
                    this.db = client.db(this.config.dbName)
                    resolve(this.db)
                })
                return
            }
            resolve(this.db)
        })
    }
    find(collectName,json={}){
        return new Promise((resolve,reject)=>{
            this.connect().then(db=>{
                let result = db.collection(collectName).find(json)
                result.

以上是关于koa框架和mongodb数据库,一小时快速入门和直击实战详细解读,建议收藏的主要内容,如果未能解决你的问题,请参考以下文章

koa框架和mongodb数据库,一小时快速入门和直击实战详细解读,建议收藏

koa框架和mongodb数据库,一小时快速入门和直击实战详细解读,建议收藏

快速搭建可用于实战的koa2+mongodb框架

Koa快速入门教程

koa框架的快速入门与使用

快速入门koa2