koa框架12 ctx属性
属性获取
属性 | 说明 | 可能的值 |
---|---|---|
method | 请求方法 | GET |
url | 完整请求路径 | /xxx/xxx/api?xxx=xxx |
path | 路径部分 | /xxx/xxx |
query | get参数 | {type:‘a’,p:12} |
querystring | get参数字符串 | ?type=a&p=12 |
host | 域名+端口 | localhost:8080 |
hostname | 域名 | localhost |
protocol | 协议 | http |
secure | 是否安全协议 | false |
ip | 访客ip地址 | xx.xx.xx.xx |
origin | 域:协议+域名+端口 | http://localhost:8080 |
其中我们可以通过ip属性写一个后台返回ip信息的api
ip信息api
由于我们要使用第三方的ip库地址,所以我们要使用http原生模块进行请求,请求是一个异步的,而我们koa都是使用async,实现异步语法同步写,所以我们要将这个请求封装成一个通用的ptomise
创建一个js文件,文件名自己想
const http = require("http");
module.exports = function(url) {
return new Promise((resolve, reject) => {
const req = http.request(url, res => {
let arr = [];
res.on("data", data => {
arr.push(data);
});
res.on("end", () => {
const buf = Buffer.concat(arr);
resolve(buf);
});
});
req.end();
//抛出错误
req.on("error", err => {
reject(err);
});
});
};
先引用http模块
模块化导出一个方法,方法接收一个url地址参数。
然后return出这个promise对象,在promise的回调里,我们创建http的网页请求request,两个参数,第一个为要请求的url地址,第二个为连接创建完毕后的回调函数。
request本身会返回一个request对象,我们本身只需要连接完毕就断开,不需要长期连接,所以使用end方法结束连接。
由于可能会产生错误,我们要使用on方法监听error事件,如果有,则使用promise的reject方法抛出错误。
连接进行时,我们的数据时一小段一小段的传输过来的,所以我们创建一个arr数组,监听request的res对象的data事件,每次触发我们就往数组里push传过来的data数据。
res对象再监听end事件,end事件触发表示数据传输完毕,我们可以进行操作了,由于传输都是二进制数据,而且又是数组保存,我们需要使用二进制对象 Buffer的concat方法,把数组连接成一长串二进制字符,然后将这个字符resolve传出去。
此时我们在后端引入这个promise中间件
const prom = require("./promise");
router.get("/", async ctx => {
const ip = ctx.ip;
const data = await prom(`http://ip-api.com/json/${ip}?lang=zh-CN`);
ctx.body = JSON.parse(data.toString());
});
我们await这个中间件方法,传入地址,等待他返回内容,data就会是其返回的二进制文件,我们再将它转为字符,由于返回的是json,所以用json的方法解析,然后给body,这样浏览器就能看到对应的信息了。
由于我们这个是异步操作,await本身也没有捕获错误能力,我们需要使用try来进行错误捕获。
router.get("/", async ctx => {
try {
const ip = ctx.ip;
const data = await prom(`http://ip-api.com/json/${ip}?lang=zh-CN`);
ctx.body = JSON.parse(data.toString());
} catch (e) {
ctx.body = "ip地址解析失败";
}
});
全局属性
ctx作为上下文对象,可以用于共享参数,官方提供了两个属性,一个为context和state。
context
context是在server对象上的,这个server就是new出来的Koa框架的构造函数所赋值的变量名,一般都用server这个变量名。
他类似于js中对象的prototype属性,在context上添加的属性,可以通过ctx对象调用。
const Koa = require("koa");
const Router = require("koa-router");
const server = new Koa();
server.listen(8080);
//创建路由
const router = new Router();
server.context.a = 12;
router.get("/", async ctx => {
console.log(ctx.a); //12
});
server.use(router.routes());
context一般用于添加一些通用的方法,比如上面我们自己写的promise封装文件。
用于扩展koa没有的方法或者属性。
state
state是作用于ctx对象的,也就是一个ctx的属性,官方意于如果所有的东西都写在context上,容易会发生覆盖,因为原来可能就已经有对应的名称了,而state则是一个空的对象,我们可以在里面添加任何东西都不用担心会覆盖原来的属性。
router.get("/", async ctx => {
ctx.state.login = true;
console.log(ctx.state.login); //true
});
特性检测
用于检测客户端是否支持某种数据,以及最优先的 选项
语言检测
检测客户端能支持什么样的语言,可以用来做全球化的多语言适配
const lang = ctx.acceptsLanguages(["zh","ja","en","fr"]);
lang会返回客户端都能接受参数里面最佳的语言。
acceptsLanguages中的参数,zh,en这些顺序都无所谓,随便,但是有两种传参方式,一种是传数组,数组里面有语言,第二种就是不要数组,两种方式都是等价的。
const lang = ctx.acceptsLanguages("zh","ja","en","fr");
数据类型
检测浏览器支持的最佳网页类型,这个一般都用不上,因为现在大家都知道,浏览器当然是html文件类型了。
const type = ctx.accepts("html","xhtml","jpg");
编码检测
用于检测浏览器支持什么编码,一般来讲,市面上的浏览器,99%都是支持gzip的。
const coding = ctx.acceptsEncodings("gzip","deflate","bz");
字符集检测
用于检测浏览器支持什么样的字符格式,当然是utf-8了啊,所以这个也用处不大
const charset = ctx.acceptsCharsets("utf-8","gb2312","big5");
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据