使用koa搭建web应用api详解

2019-07-18  本文已影响0人  shenjianbo

Koa

基于NodeJs的web应用框架,由Express的原班人马打造,致力于提供一个轻量级的框架,几乎所有功能都需要第三方的中间件来辅助完成,使用了node的新特性,比express更简洁,更轻量

express与koa对比

koa相对于express更加年轻,意味着express生态更加成熟,koa比express更加轻量,本身只提供一个架子,几乎所有功能都需要依赖于第三方插件,而express自身就集成了许多功能,这也意味着express更加笨重,express对于初学者更加友好,自身的功能足够使用,而koa则学习成本更高,毕竟连核心的路由也去掉了,都需要通过学习第三方中间件来实现,而很多中间件的功能一样,api却不同,koa使用了很多node的新特性及es6的新特性,而express则语法上比较陈旧一点,但是兼容性更好

koa起步

生成项目文件并初始化包管理文件package.json

mkdir myapp && cd myapp && npm init -y

下载koa模块

npm install koa -S

创建app.js

touch app.js

编辑app.js

// 引入koa模块
const Koa = require('koa');
// 实例化koa
const app = new Koa();
// 创建接受Context对象的函数,Context由koa提供,表示一次对话的上下文
const main = ctx => {
  // ctx包含请求及响应对象,通过响应对象的body设置返回的内容
  ctx.response.body = 'Hello World';
}
// 使用加载main函数,注册到koa
app.use(main);
// 监听并启动服务
app.listen(3000);

衔接上文对象,ctx.response.type设置返回数据类型

const Koa = require('koa');
const app = new Koa();
const main = ctx => {
  // text或text/plain纯文本
  // html或text/html解析为html
  // json
  ctx.response.type = 'html';
  ctx.response.body = 'Hello World';
}
app.use(main);
app.listen(3000);

路由

简单来说路由间url到函数的映射,一个url指向一个地址,由此执行一个对应的规则,通常在web中理解为一个函数,而url到这个函数的过程称之为路由

原生路由

网站一般都是由多个页面组成的,不同的url指向不同的页面,在koa中可以通过ctx.request.path获取用户请求的路径

我们可以将我们的body指向一个网页模板,通过fs.createReadStream()获取文件流

const Koa = require('koa');
const fs = require('fs');
const app = new Koa();
const main = ctx => {
 ctx.response.type = 'html';
 if(ctx.request.path === '/') {
   ctx.response.body = fs.createReadStream('./index.html');
 }
 else {
   ctx.response.body = '页面未找到';
 }
}
app.use(main);
app.listen(3000);

中间件

简单来说就是处于操作系统和应用软件之间的一个类或者说插件,具有承上启下的作用,用于连接两个模块,可重用的与业务逻辑无关的各种组件

koa-route模块

koa-route是koa的一个第三方中间件,当然还有koa-router,文章里的相对简单一点

const Koa = require('koa');
          
const app = new Koa();
          
const fs = require('fs');
          
const route = require('koa-route');
          
const about = require('./about.js');
          
const home = require('./home.js');
          
app.use(route.get('/home', home));
          
app.use(route.get('/about', about));
          
app.listen(3000);

home.js

const home = cxt => {
   console.log(cxt)
  cxt.response.body = '首页';
}
module.exports = home;

about.js

const about = cxt => {
  cxt.response.body = '关于我们';
}
module.exports = about;

静态资源

网站的静态资源(脚本、图片、字体、样式表),假如为他们都写一个路由将会很麻烦,比如用户需要单独访问该服务地址下的一张图片就很不方便,static就类似一个web容器

这里用到了koa-static

const Koa = require('koa');
const app = new Koa();
const path = require('path');
const static = require('koa-static');
const main = static(path.join(__dirname, 'static'));
app.use(main);
app.listen(3000);

重定向

重新指定方向(路由),有时候当用户访问一个页面,当用户权限不够或者其他问题的时候,我们需要给用户一个响应,则需要重新为用户指定页面

const Koa = require('koa');
const app = new Koa();
const route = require('koa-route');
const redirect = ctx => {
  ctx.response.redirect('/');
};
const main = ctx => {
  ctx.response.body = '首页';
};
            
app.use(route.get('/redirect', redirect));
app.use(route.get('/', main));
app.listen(3000);

异步中间件

当出现异步操作时,比如异步读取文件,查询数据库等,我们就必须把我们的中间件设置为异步

const Koa = require('koa');
const app = new Koa();
const route = require('koa-route');
const fs = require('fs');
function readFile() {
  return new Promise((resolve, reject) => {
    fs.readFile('./index.html', (err, data) => {
      resolve(data);
    })
  })
}
const main = async function (ctx, next) {
  ctx.response.type = 'html';
  ctx.response.body = await readFile();
 };
            
app.use(main);
app.listen(2000);

中间件的合成

koa-compose模块可以将多个中间件合成为一个

const compose = require('koa-compose');
          
const logger = (ctx, next) => {
  console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`);
  next();
}
          
const main = ctx => {
  ctx.response.body = 'Hello World';
};
          
const middlewares = compose([logger, main]);
app.use(middlewares);

错误处理

如果代码运行过程中发生错误,我们需要把错误信息返回给用户。HTTP 协定约定这时要返回500状态码。

ctx.throw()

const Koa = require('koa');
const app = new Koa();
const main = async function (ctx, next) {
  ctx.throw(500)
};
            
app.use(main);
app.listen(2000);

404错误

const main = ctx => {
  ctx.response.status = 404;// 等同于ctx.throw(404)
  ctx.response.body = 'Page Not Found';
};

错误处理中间件

const handler = async (ctx, next) => {
  try {
    await next();
  }
  catch (err) {
    ctx.response.status = err.statusCode || err.status || 500;
    ctx.response.body = {
      message: err.message
    };
  }
};
          
const main = ctx => {
  ctx.throw(500);
};
          
app.use(handler);
app.use(main);

文章中多次用到next,简单理解就是当我们同时使用两个中间件的时候,会发现先use的会执行,而后面的中间件则不会执行,这时候我们需要使用next把我们中间件的执行权交给下一个中间件

async和await需要配合使用,await会给其后的表达式包裹一个promise进行返回

以上参考阮一峰大大的文章!!!

上一篇下一篇

猜你喜欢

热点阅读