属性获取

属性说明可能的值
method请求方法GET
url完整请求路径/xxx/xxx/api?xxx=xxx
path路径部分/xxx/xxx
queryget参数{type:‘a’,p:12}
querystringget参数字符串?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");
分类: Node 标签: nodekoactx

评论

暂无评论数据

暂无评论数据

目录