koa 是由 Express 原班人马打造的,一个基于 Node.js 平台的 Web 开发框架
Express 是基于 ES5 的语法,随着新版 Node.js 开始支持 ES6 ,该团队重新编写诞生了 koa 1.0 ,而 koa2.0 则是更是超前的基于 ES7
npm i koa
// 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
const Koa = require('koa');
// 创建一个Koa对象表示web app本身:
const app = new Koa();
app.use( ... )
// 在端口3000监听:
app.listen(3000);
在 path 上安装中间件,每当请求的路径的基路径和该path匹配时,都会导致该中间件函数被执行,如果 path 没有被设定,那么默认为 /
app.use('/admin', function(req, res) {
console.log(req.originalUrl); // '/admin/new'
console.log(req.baseUrl); // '/admin'
console.log(req.path); // '/new'
});
app.use(async (ctx, next) => {
await next(); // 处理下一个异步函数
ctx.response.type = 'text/html' // 设置 response 的 Content-Type
ctx.response.body = '<h1>Hello, koa2!</h1>' // 设置 response 的内容
})
由 async 标记的函数称为异步函数,在异步函数中,可以用 await 调用另一个异步函数,这两个关键字将在 ES7 中引入(用法看上去类似 Promise)
上述代码中,参数 ctx 是由 koa 传入的封装了 request 和 response 的变量,我们可以通过它访问 request 和 response, next 是 koa 传入的将要处理的下一个异步函数
对于每一个 http 请求, koa 将调用通过 app.use() 注册的 async 函数,并传入 ctx 和 next 参数
实例:
const Koa=require('koa');
const app=new Koa();
app.use(async (ctx, next) => {
console.log('第一1');
await next(); // 调用下一个middleware
console.log('第一2');
});
app.use(async (ctx, next) => {
console.log('第二1');
await next(); // 调用下一个middleware
console.log('第二2');
});
app.use(async (ctx, next) => {
console.log('第三1');
await next();
console.log('第三2');
});
app.listen(3000);
// 打印结果如下:
// 第一1
// 第二1
// 第三1
// 第三2
// 第二2
// 第一2
koa-router 负责处理 URL 映射,通过它可以更便捷的对 URL 进行操作
const router = require('koa-router')(); // 引入 koa-router
……
// add router middleware:
app.use(router.routes());
注意导入 koa-router 的语句最后的 () 是对函数调用
通过使用 koa-router ,我们可以处理一些更复杂的 URL 操作,比如 GET 请求
// log request URL:
app.use(async (ctx, next) => {
console.log(`<h1>Hello, ${name}!</h1>`);
await next();
});
// add url-route:
router.get('/hello/:name', async (ctx, next) => {
var name = ctx.params.name; // 通过 ctx.params.name 可以获取 URL 带来的变量
ctx.response.body = `<h1>Hello, ${name}!</h1>`;
});
用 router.get('/path', async fn) 处理的是 get 请求
用 router.post('/path', async fn) 处理 post 请求
需要注意,post 请求的数据,无法正确为客户端解析成正确的 request 的 body ,此时需要利用 koa-bodyparser 组件实现解析
const router = require('koa-router')(); // 引入 koa-router
const bodyParser = require('koa-bodyparser');
app.use(bodyParser()); // 在 router.routes 之前注入 bodyParser
……
router.post('/path', async fn)
……
// add router middleware:
app.use(router.routes());
app.listen(3000);
注意 koa-bodyparser 必须在 router 之前被注册到 app 对象上
为了使目录结构更为美观,可以将所有的 URL 处理函数都提取出来
// index.js
var fn_index = async (ctx, next) => { …… };
var fn_signin = async (ctx, next) => { …… };
module.exports = {
'GET /': fn_index,
'POST /signin': fn_signin
};
app.js 页面在获取上,廖雪峰的实例代码略显复杂,如下
var fs = require('fs') // 引入 Node.js 核心模块 fs
// 通过 fs.readdirSync 同步读取 /controllers 目录下的文件
// 该源实例 index.js 存放于 /controllers 目录下
var files = fs.readdirSync(__dirname + '/controllers');
// 源实例注解:这里可以用sync是因为启动时只运行一次,不存在性能问题
// 过滤该目录下所有 .js 后缀的文件
var js_files = files.filter((f)=>{
return f.endsWith('.js');
});
// 循环所有 .js 后缀的文件
for (var f of js_files) {
// 动态引入每一个 js 文件,此处并非真实引入
let mapping = require(__dirname + '/controllers/' + f);
for (var url in mapping) { // 此时的 mapping 为每一个 .js 文件的 exports 对象,循环该对象
if (url.startsWith('GET ')) { // 如果对象键名 url 已 'GET ' 开头
var path = url.substring(4); // 提取键名中的路径部分,此处是 '/'
router.get(path, mapping[url]);
} else if (url.startsWith('POST ')) { // 如果对象键名 url 已 'POST ' 开头
var path = url.substring(5); // 提取键名中的路径部分,此处是 '/signin'
router.post(path, mapping[url]);
} else {
// 无效的URL:
console.log(`invalid URL: ${url}`);
}
}
}
可选的 options 参数可以是指定编码的字符串,也可以是具有 encoding 属性的对象,该属性指定用于传给回调的文件名的字符编码。 如果 encoding 设置为 'buffer',则返回的文件名是 Buffer 对象。
__dirname
在每个 Node.js 模块中,除 require 、exports 等模块之外还都包含两个特殊成员
__dirname 动态获取当前文件模块所属目录的绝对路径__filename 动态获取当前文件的绝对路径str.startsWith(searchString [, position])
startsWith() 方法用来判断当前字符串是否是以另外一个给定的子字符串开头的,根据判断结果返回 true 或 false
searchString 要搜索的子字符串position 在 str 中搜索 searchString 的开始位置,默认值为 0,也就是真正的字符串开头处endsWith()
方法用于测试字符串是否以指定的后缀结束。如果参数表示的字符序列是此对象表示的字符序列的后缀,则返回 true,否则返回 false
stringObject.substring(start,stop)
substring() 方法用于提取字符串中介于两个指定下标之间的字符
start 必需。一个非负的整数,规定要提取的子串的第一个字符在 stringObject 中的位置
stop 可选。一个非负的整数,比要提取的子串的最后一个字符在 stringObject 中的位置多 1。
如果省略该参数,那么返回的子串会一直到字符串的结尾
将以上代码复制一份,命名为 controller.js ,优化代码,如下
var fs = require('fs') // 引入 Node.js 核心模块 fs
const router = require('koa-router')(); // 引入 koa-router
// 函数 addMapping 包含两个参数
// router koa-router 实例
// mapping 所有路由 url
function addMapping(router, mapping) {
for (var url in mapping) { // 此时的 mapping 为每一个 .js 文件的 exports 对象,循环该对象
if (url.startsWith('GET ')) { // 如果对象键名 url 已 'GET ' 开头
var path = url.substring(4); // 提取键名中的路径部分,此处是 '/'
router.get(path, mapping[url]);
} else if (url.startsWith('POST ')) { // 如果对象键名 url 已 'POST ' 开头
var path = url.substring(5); // 提取键名中的路径部分,此处是 '/signin'
router.post(path, mapping[url]);
} else {
console.log(`invalid URL: ${url}`);
}
}
}
function addControllers(router, dir) {
// 通过 fs.readdirSync 同步读取 /controllers 目录下的文件
// 该源实例 index.js 存放于 /controllers 目录下
var files = fs.readdirSync(__dirname + '/' + dir);
// 过滤该目录下所有 .js 后缀的文件
var js_files = files.filter((f) => {
return f.endsWith('.js');
});
// 循环所有 .js 后缀的文件
for (var f of js_files) {
// 动态引入每一个 js 文件,此处并非真实引入
let mapping = require(__dirname + '/' + dir + '/' + f);
// 调用 addMapping 函数,并将
addMapping(router, mapping);
}
}
module.exports = function (dir) {
let controllers_dir = dir || 'controllers', // 如果不传参数,扫描目录默认为'controllers'
router = require('koa-router')(); // 动态引入 koa-router 组件
addControllers(router, controllers_dir);
// 实参 router 为实例化 router
// 实参 controllers_dir 为路径
return router.routes(); // add router middleware
};
这样一来,我们在 app.js 的代码又简化了
// 导入 controller middleware:
const controller = require('./controller');
// 使用 middleware:
app.use(controller());
文章已同步我的个人博客:《Node学习笔记 初识Koa》
koa是一个基于node实现的一个新的web框架,它是由express框架的原班人马打造的。它的特点是优雅、简洁、表达力强、自由度高。它更express相比,它是一个更轻量的node框架
koa-easywechat注意:koa-easywechat中间件要写在最前面,也就是要第一个use,因为我在ctx上挂载了一个wechat对象,这个对象实现了大部分的微信接口,这样才能保证开发者在自己的写路由里,获取到ctx.wechat进行自己的业务开发
我们知道,Koa 中间件是以级联代码(Cascading) 的方式来执行的。类似于回形针的方式,今天这篇文章就来分析 Koa 的中间件是如何实现级联执行的。在 koa 中,要应用一个中间件,我们使用 app.use()
Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。
安装 koa、简单使用、级联中间件的概念、获取get请求参数、获取post表单数据和文件上传、路由中间件 koa-router
想使用nodejs(koa)搭建一个完整的前后端,完成数据的增删改查,又不想使用数据库,那使用json文件吧。本文介绍了基于koa的json文件的增、删、改、查。
对于一个服务器应用来说,日志的记录是必不可少的,我们需要使用其记录项目程序每天都做了什么,什么时候发生过错误,发生过什么错误等等,便于日后回顾、实时掌握服务器的运行状态,还原问题场景
Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的。当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件。当在下游没有更多的中间件执行后,堆栈将展开并且每个中间件恢复执行其上游行为
上传文件在开发中是很常见的操作,今天我选择使用koa-multer中间件来实现这一功能,除了上传文件外,我还会对文件上传进行限制,以及发生上传错误时的处理。由于原来的 koa-multer 已经停止维护,我们要使用最新的 @koa/multer
这篇文章会讲些什么?如何从零开始完成一个涵盖Koa核心功能的Node.js类库,从代码层面解释Koa一些代码写法的原因:如中间件为什么必须调用next函数、ctx是怎么来的和一个请求是什么关系
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!