Learn koa in 10 minutes

know koa

The successor to express, lighter and smaller.

basic use

The middleware registered by koa provides two parameters:

  • ctx: Context object;
  • Koa does not separate req and res like express, but uses them as attributes of ctx;
  • ctx represents the context object requested sequentially;
    • ctx.request: Get the request object;
    • ctx.response: get the response object;
  • next: essentially a dispatch, similar to the previous next;

In express, if end is not called in the middleware, the request will be suspended. And koa returns NOT FOUND to close the connection after all the middleware is executed.

Without end, how does koa end the request manually? through the body. such as settingctx.response.body = "请求结束"

const Koa = require('koa');

// 实例化
const app = new Koa();

app.use((ctx, next) => {
    
    
  ctx.response.body = "Hello World";
});

app.listen(8000, () => {
    
    
  console.log("koa初体验服务器启动成功~");
});

middleware

The app object created by koa can only register middleware through the use method:
the following registration methods are not provided:

  • methods method:app.get('/.post')
  • path method:app.use('/home', (ctx, next) => {})
  • Continuous Registration:app.use((ctx, next) => {}, (ctx, next) => {})

But how do we separate paths and methods in real development?
Method 1: Judge according to the request itself;
Method 2: Use third-party routing middleware;

app.use((ctx, next) => {
    
    
  if (ctx.request.url === '/login') {
    
    
    if (ctx.request.method === 'GET') {
    
    
      console.log("来到了这里~");
      ctx.response.body = "Login Success~";
    }
  } else {
    
    
    ctx.response.body = "other request~";
  }
});

routing

The koa official does not provide us with a routing library, we can choose a third-party library: koa-router
installation:npm i koa-router

koa-router can support the same as use in express, defining paths and linking definition middleware.

We can first encapsulate a user.router.js file: register router.routes() as middleware in the app:

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

// 实例化路由,并且添加公共路径前缀
const router = new Router({
    
    prefix: "/users"});

// router 中就可以和 express 一样使用 methods 的方式注册中间件
router.get('/', (ctx, next) => {
    
    
  ctx.response.body = "User Lists~";
});

router.put('/', (ctx, next) => {
    
    
  ctx.response.body = "put request~";
});

module.exports = router;

The routes method of the routing instance registers routing middleware.

const Koa = require('koa');

const userRouter = require('./router/user');

const app = new Koa();

app.use(userRouter.routes());
app.use(userRouter.allowedMethods());

app.listen(8000, () => {
    
    
  console.log("koa路由服务器启动成功~");
});

When some methods are not defined, for example, there is no middleware registered for the post method above. If the client initiates a post request, NOT FOUND is returned. This doesn't make sense.
Then you can use the allowedMethods method of the routing object.

allowedMethods is used to determine whether a method is supported:

  • If we request get, then it is a normal request, because we have implemented get;
  • If we request put, delete, patch, then an error will be automatically reported: Method Not Allowed, status code: 405;
  • If we request link, copy, lock, then an error will be automatically reported: Not Implemented, status code: 501;

request data processing

params and query

Because there is no path writing in koa's use, the request data is generally processed in the route.
Both params and query data can be directly fetched from the request object request.

const Koa = require('koa');

const app = new Koa();
const Router = require('koa-router');

const userRouter = new Router({
    
    prefix: '/users'});

userRouter.get('/:id', (ctx, next) => {
    
    
  console.log(ctx.request.params);
  console.log(ctx.request.query);
})

app.use(userRouter.routes());

app.listen(8000, () => {
    
    
  console.log("参数处理服务器启动成功~");
});

json and urlencoded

ctx.response.body in koa is also undefined, and the data in the request body cannot be obtained. So you need to use a third-party library: koa-bodyparser. After that, you can directly read the data in the body as in express.
Install:npm i koa-bodyparser

And it can not only parse json, but also urlencoded data, but it cannot parse form-data.

const Koa = require('koa');
const bodyParser = require('koa-bodyparser');

const app = new Koa();

app.use(bodyParser());

app.use((ctx, next) => {
    
    
  console.log(ctx.request.body);
  ctx.response.body = "Hello World";
});

app.listen(8000, () => {
    
    
  console.log("koa初体验服务器启动成功~");
});

form-data

Express uses multer to parse form-data, and of course koa also uses a third-party library, which uses multer koa-multer.
Install:npm i koa-multer

Parse non-file data

It is not recommended to use any method globally in express, try to use it locally in methods for paths. The same is true in koa, try to use it in routing, and koa routing also supports continuous definition of middleware.

Although we rarely use the form-data format to upload ordinary data, there is a big pit to pay attention to:

  • For normal form-data data, koa-multer doesn't put it in ctx.request.body, but in ctx.req.body!

What is the difference between req and request?

  • request is the request object implemented by koa itself. req is the request object of http module in native nodejs.
const Koa = require('koa');
const Router = require('koa-router')
const multer = require('koa-multer')

const app = new Koa();

const router = new Router({
    
    prefix: "/user"})

const upload = multer()

router.post("/", upload.any(), (ctx, next) => {
    
    
  console.log(ctx.req.body); // [Object: null prototype] { name: 'zs', age: '18' }
  console.log(ctx.request.body); // undefined
  ctx.response.body = "test";
})

app.use(router.routes())

app.listen(8000, () => {
    
    
  console.log("koa初体验服务器启动成功~");
});

File Upload

It is the same as using multer in express. However, it should be noted that koa-multer writes all the data into req, not request.

const Koa = require('koa');
const Router = require('koa-router')
const multer = require('koa-multer')
const path = require("path")

const app = new Koa();

const uploadRouter = new Router({
    
    prefix: "/user"})

const storage = multer.diskStorage({
    
    
  destination: (req, file, cb) => {
    
     // 指定存储目录
    cb(null, './uploads');
  },
  filename: (req, file, cb) => {
    
     // 指定存储的文件名
    cb(null, Date.now() + path.extname(file.originalname)); // 时间戳+后缀
  }
})

const upload = multer({
    
    
  storage
})

uploadRouter.post("/", upload.single("pic"), (ctx, next) => {
    
    
  console.log(ctx.req.file); 
  ctx.response.body = "test";
})

app.use(uploadRouter.routes())

app.listen(8000, () => {
    
    
  console.log("koa初体验服务器启动成功~");
});

// {
    
    
//   fieldname: 'pic',
//   originalname: '@-?�-03.jpg',
//   encoding: '7bit',
//   mimetype: 'image/jpeg',
//   destination: './uploads',
//   filename: '1664906028636.jpg',
//   path: 'uploads\\1664906028636.jpg',
//   size: 214812
// }

data response

Output: body Set the response body to one of the following:

  • string : string data
  • Buffer: Buffer data
  • Stream : stream data
  • Object|| Array: object or array (commonly used)
  • null : do not output anything

Koa will automatically set status to 200 or 204 if response.status has not been set.

const Koa = require('koa');

const app = new Koa();

app.use((ctx, next) => {
    
    

  // 设置内容

  // ctx.response.body

  // ctx.response.body = "Hello world~"

  // ctx.response.body = {
    
    
  //   name: "zs",
  //   age: 18,
  //   avatar_url: "https://abc.png"
  // };

  // 设置状态码
  // ctx.response.status = 400;
  // ctx.response.body = ["abc", "cba", "nba"];

  // ctx.response.body = "Hello World~";
  ctx.status = 404;
  ctx.body = "Hello Koa~"; // 这种方式更简洁,实际背后还是执行 ctx.request.body
});

app.listen(8000, () => {
    
    
  console.log("koa初体验服务器启动成功~");
});

static server

Koa does not have built-in deployment-related functions, so we need to use a third-party library: koa-static
installation:npm i koa-static

The deployment process is similar to express:

const Koa = require('koa');
const staticAssets = require('koa-static');

const app = new Koa();

app.use(staticAssets('./build'));

app.listen(8000, () => {
    
    
  console.log("koa初体验服务器启动成功~");
});

error handling

The transaction bus is also supported in the app. So error handling can be done in a transactional bus way: let app emit emit an error, and then use on to listen.
The app object can also be obtained in the context, so you can use ctx to obtain the app object.
Why not use the app object directly, because it is generally operated in the route, and it is not easy to get the app object in the route.

const Koa = require('koa');

const app = new Koa();

app.use((ctx, next) => {
    
    
  const isLogin = false;
  if (!isLogin) {
    
    
    // 发出错误
    ctx.app.emit('error', new Error("您还没有登录~"), ctx);
  }
});

// 监听错误
app.on('error', (err, ctx) => {
    
    
  ctx.status = 401;
  ctx.body = err.message;
})

app.listen(8000, () => {
    
    
  console.log("koa初体验服务器启动成功~");
});

The difference between koa and express

The biggest difference between koa and express lies in the implementation of the next function. The next function in koa returns a promise, while the next function in express is an ordinary function.
This difference leads to differences in how they handle asynchrony.

In addition, the function to execute the next middleware in koa is actually called dispatch, just to follow the habit in express, when we use it, we use next as the parameter name.

How is middleware chained?

Both koa and express are the same, and the execution process of the middleware is actually equivalent to recursive calls.
As follows: next in middleware1 will execute the middleware function in middleware2, next in middleware2 will execute the middleware function in middleware3, and finally return to middleware1. After the next function in middleware1 is executed, continue to execute the code res.end after next.

const express = require('express');

const app = express();

const middleware1 = (req, res, next) => {
    
    
  req.message = "aaa";
  next();
  res.end(req.message); // aaabbbccc
}

const middleware2 = (req, res, next) => {
    
    
  req.message += "bbb";
  next();
}

const middleware3 = (req, res, next) => {
    
    
  req.message += "ccc";
}

app.use(middleware1, middleware2, middleware3);

app.listen(8000, () => {
    
    
  console.log("服务器启动成功~");
})

asynchronous processing

Koa and express both recursively execute middleware, so what if an asynchronous request is sent in the middleware? How to get asynchronous data.
We will find that ordinary middleware is synchronous, and they cannot get the results of asynchronous requests. Either koa or express.

const express = require('express');
const axios = require('axios');

const app = express();

const middleware1 = (req, res, next) => {
    
    
  req.message = "aaa";
  next();
  res.end(req.message); // 结果为:aaabbb
}

const middleware2 = (req, res, next) => {
    
    
  req.message += "bbb";
  next();
}

const middleware3 = async (req, res, next) => {
    
    
  const result = await axios.get('http://localhost:9000'); // 注:服务器将返回 ccc
  req.message += result.data;
}

app.use(middleware1, middleware2, middleware3);

app.listen(8000, () => {
    
    
  console.log("express 服务器启动成功~");
})

Express gets data from asynchronous requests

Don't put asynchronous requests in other middleware, put them in the middleware that needs to use the request data.

const express = require('express');
const axios = require('axios');

const app = express();

const middleware1 = async (req, res, next) => {
    
    
  req.message = "aaa";
  next();
  const result = await axios.get('http://localhost:9000'); // 注:服务器将返回 ccc
  res.end(req.message + result.data); // 结果为:aaabbbccc
}

const middleware2 = (req, res, next) => {
    
    
  req.message += "bbb";
  next();
}

// const middleware3 = async (req, res, next) => {
    
    
//   const result = await axios.get('http://localhost:9000'); // 注:服务器将返回 ccc
//   req.message += result.data;
// }

app.use(middleware1, middleware2, middleware3);

app.listen(8000, () => {
    
    
  console.log("服务器启动成功~");
})

koa gets data from asynchronous requests

Because each dispatch function in koa returns a promise, we can use await continuously to await the entire chain of middleware . There is no need to change the position of the asynchronous request like in express.

const Koa = require('koa');
const axios = require('axios');

const app = new Koa();

const middleware1 = async (ctx, next) => {
    
    
  ctx.message = "aaa";
  await next();
  ctx.body = ctx.message;
}

const middleware2 = async (ctx, next) => {
    
    
  ctx.message += "bbb";
  await next();
}

const middleware3 = async (ctx, next) => {
    
    
  const result = await axios.get('http://localhost:9000');
  ctx.message += result.data;
}

app.use(middleware1);
app.use(middleware2);
app.use(middleware3);

app.listen(8000, () => {
    
    
  console.log("koa 服务器启动成功~");
})

Guess you like

Origin blog.csdn.net/qq_43220213/article/details/129646204