Koa is the next generation of Express’s Node.js-based Web framework. Built by the original Express team, koA uses async functions, discards callback functions, and significantly enhances error handling. Koa doesn’t bundle any middleware, giving it a clean feel, small size and clean programming.

Koa website link: koa.bootcss.com/

history

Express

Express is the most popular web framework of the first generation. It encapsulates the HTTP of Node.js and is used as follows:

var express = require('express');
var app = express();

app.get('/'.function (req, res) {
    res.send('Hello World! ');
});

app.listen(3000.function () {
    console.log('Server started successfully');
});
Copy the code

While the Express API is simple, it is based on ES5 syntax, and there is only one way to implement asynchronous code: a callback. If there are too many levels of asynchronous nesting, the code can be ugly to write:

app.get('/test'.function (req, res) {
    fs.readFile('/file1'.function (err, data) {
        if (err) {
            res.status(500).send('read file1 error');
        }
        fs.readFile('/file2'.function (err, data) {
            if (err) {
                res.status(500).send('read file2 error');
            }
            res.type('text/plain');
            res.send(data);
        });
    });
});
Copy the code

While you can use libraries like Async to organize asynchronous code, writing async with callbacks is just too painful!

koa1

With the new version of Node.js starting to support ES6, the Express team rewrote the next generation Web framework koA based on the GENERATOR of ES6. In contrast to Express, KOA 1.0 uses a generator for asynchrony and the code looks synchronous:

var koa = require('koa');
var app = koa();

app.use('/test'.function* () {
    yield doReadFile1();
    var data = yield doReadFile2();
    this.body = data;
});

app.listen(3000.function () {
    console.log('Server started successfully');
});
Copy the code

koa2

The KOA team didn’t stop at KOA 1.0, they were way ahead of the game with KOA2 based on ES7. Compared to KOA 1, KOA2 fully uses Promises with async to implement async.

app.use(async (ctx, next) => {
    await next();
    var data = await doReadFile();
    ctx.response.type = 'text/plain';
    ctx.response.body = data;
});
Copy the code

Koa development environment setup

Installation Node. Js

Since Node.js v7.6.0 fully supports async/await and does not require flags, node.js environments should be above 7.6.0. Node.js environment version v7.6 or later, NPM version 3.x or later.

Install Koa2

# install koa2 NPM install koaCopy the code

If the installation error, generally is the network speed problem, you can use CNPM to install.

hello Koa2

// In koA2, we import a class, so use uppercase Koa:
const Koa = require('koa')
// Create a Koa object representing the Web app itself:
const app = new Koa()

// For any request, app will call this asynchronous function to handle the request:
app.use( async ( ctx ) => {
  ctx.body = 'hello koa2'
})

app.listen(3000)
console.log('Server started successfully')
Copy the code

On the command line, enter:

node index.js
Copy the code

Then type http://127.0.0.1:3000 into your browser to see the results.

Use the async/await

Quickly understand

Copy the following code, paste it in chrome’s console console, and press Enter to execute

function getSyncTime() {
  return new Promise((resolve, reject) = > {
    try {
      let startTime = new Date().getTime()
      setTimeout(() = > {
        let endTime = new Date().getTime()
        let data = endTime - startTime
        resolve( data )
      }, 500)}catch ( err ) {
      reject( err )
    }
  })
}

async function getSyncData() {
  let time = await getSyncTime()
  let data = `endTime - startTime = ${time}`
  return data
}

async function getData() {
  let data = await getSyncData()
  console.log( data )
}

getData()
Copy the code

Results:

From the above examples we can see the characteristics of async/await:

  • Asynchronous logic can be written synchronously
  • The bottom await returns a Promise object
  • You can replace traditional callback nesting with synchronous writing of multiple async functions

Request data acquisition

GET Requests data acquisition

In KOA2, GET requests are received through request in two ways: Query and QueryString.

  • Query: Returns a formatted argument object.
  • Querystring: Returns a request string.

Since CTX has a direct reference to the request API, it is also possible to GET a GET request directly in CTX. CTX is also divided into Query and queryString.

const Koa = require('koa')
const app = new Koa()

app.use( async ( ctx ) => {
  let url = ctx.url
  // From the context's request object
  let request = ctx.request
  let req_query = request.query
  let req_querystring = request.querystring

  // Directly from the context
  let ctx_query = ctx.query
  let ctx_querystring = ctx.querystring

  ctx.body = {
    url,
    req_query,
    req_querystring,
    ctx_query,
    ctx_querystring
  }
})

app.listen(3000.() = > {
  console.log('Server started successfully')})Copy the code

The POST request parameters are obtained

For POST request processing, KOA2 does not encapsulate the method of obtaining parameters, which need to be obtained by parsing the native Node.js request object req in the context.

Steps to get a Post request:

  1. Parse the native Nodex.js object req in context CTX.
  2. Parse the POST form data into query String-strings (for example, user=jspang&age=18).
  3. Convert the string to JSON format.

Ctx. req is the node.js native HTTP request object provided by context, which can get more content and is suitable for our in-depth programming. Ctx. response is the encapsulated response object of the context, and ctx.res is the node.js native HTTP response object provided by the context.

Case code demo:

const Koa = require('koa')
const app = new Koa()

app.use( async ( ctx ) => {

  if ( ctx.url === '/' && ctx.method === 'GET' ) {
    // Return the form page when a GET request is made
    let html = ` 

koa2 request post demo

userName



nickName



`
ctx.body = html } else if ( ctx.url === '/' && ctx.method === 'POST' ) { // When a POST request is made, the data in the POST form is parsed and displayed let postData = await parsePostData( ctx ) ctx.body = postData } else { // Other requests show 404 ctx.body = '

404!

'
}})// Parse the POST parameter of node's native request in context function parsePostData( ctx ) { return new Promise((resolve, reject) = > { try { let postdata = ""; ctx.req.addListener('data'.(data) = > { postdata += data }) ctx.req.addListener("end".function(){ let parseData = parseQueryStr( postdata ) resolve( parseData ) }) } catch ( err ) { reject(err) } }) } // Parse the POST request parameter string into JSON function parseQueryStr( queryStr ) { let queryData = {} let queryStrList = queryStr.split('&') console.log( queryStrList ) for ( let [ index, queryStr ] of queryStrList.entries() ) { let itemList = queryStr.split('=') queryData[ itemList[0]] =decodeURIComponent(itemList[1])}return queryData } app.listen(3000.() = > { console.log('Server started successfully')})Copy the code

Koa – bodyparser middleware

For POST request processing, the KOA-BodyParser middleware parses formData from the KOA2 context into ctx.request.body

Installing middleware

// Install using NPM. Note that we use -save here, as it is required in production.
npm install --save koa-bodyparser@3
Copy the code

Introduction to use

// After the installation is complete, you need to import and use it in your code. We introduce it at the top of the code with require.
const bodyParser = require('koa-bodyparser');

Because the order of middleware is important, the KoA-BodyParser must be registered with the app object before the router.
app.use(bodyParser());
Copy the code

Ctx.request. body can be directly used to obtain the POST request parameters after being used in the code, which is automatically parsed by the middleware.

Now let’s optimize the example code:

const Koa = require('koa')
const app = new Koa()
const bodyParser = require('koa-bodyparser')

// Use ctx.body to parse middleware
app.use(bodyParser())

app.use( async ( ctx ) => {

  if ( ctx.url === '/' && ctx.method === 'GET' ) {
    // Return the form page when a GET request is made
    let html = ` 

koa2 request post demo

userName



nickName



`
ctx.body = html } else if ( ctx.url === '/' && ctx.method === 'POST' ) { // When a POST request is made, the middleware koa-BodyParser parses the data in the POST form and displays it let postData = ctx.request.body ctx.body = postData } else { // Other requests show 404 ctx.body = '< h1 > 404! ' } }) app.listen(3000.() = > { console.log('Server started successfully')})Copy the code

routing

Koa2 native route implementation

Simple example

To realize the native route, you need to obtain the path entered in the address bar and jump to the destination according to the different paths. This can be done with ctx.request.url. Let’s take a look at how to get access paths through a simple example.

const Koa = require('koa')
const app = new Koa()

app.use( async ( ctx ) => {
  let url = ctx.request.url
  ctx.body = url
})
app.listen(3000)
Copy the code

This time will visit http://127.0.0.1:3000/hello/12 page output/hello / 12. In other words, the url in the context of the request object is the name of the current access path. The required route can be customized according to ctx.request.url through certain judgment or regular matching.

Customized routes

Source file directory:

. ├ ─ ─ app. Js ├ ─ ─ package. The json └ ─ ─ the view ├ ─ ─ 404 HTML ├ ─ ─ index. The HTML └ ─ ─ todo. HTMLCopy the code

The implementation of native routing requires the introduction of fs modules to read files. Then according to the route path to read, and finally returned to the page, rendering. Let’s look at a little example.

/* app.js file */
const Koa = require('koa')
const fs = require('fs')
const app = new Koa()

/** * encapsulate asynchronous file-reading methods with Promise *@param  {string} Page HTML file name *@return {promise}      * /
function render( page ) {
  return new Promise(( resolve, reject ) = > {
    let viewUrl = `./view/${page}`
    fs.readFile(viewUrl, "binary".( err, data ) = > {
      if ( err ) {
        reject( err )
      } else {
        resolve( data )
      }
    })
  })
}

/** * Get HTML content from URL *@param  {string} Url Indicates the URL of the KOA2 context, ctx.url *@return {string}     Get the HTML file content */
async function route( url ) {
  let view = '404.html'
  switch ( url ) {
    case '/':
      view = 'index.html'
      break
    case '/index':
      view = 'index.html'
      break
    case '/todo':
      view = 'todo.html'
      break
    case '/ 404':
      view = '404.html'
      break
    default:
      break
  }
  let html = await render( view )
  return html
}

app.use( async ( ctx ) => {
  let url = ctx.request.url
  let html = await route( url )
  ctx.body = html
})

app.listen(3000.() = > {
  console.log('Server started successfully')})Copy the code

Koa – the router middleware

If you rely on CTx.request. url to process routes manually, a lot of processing codes will be written. In this case, the middleware of the corresponding route is required to control the route

Install koA-Router middleware:

// The corresponding koA2 version is 7.x
npm install --save koa-router@7
Copy the code

Quick use of koA-Router:

const Koa = require('koa')
const app = new Koa()

const Router = require('koa-router')

// Child route 1
let home = new Router()
home.get('/'.async ( ctx )=>{
  let html = ` 
       `
  ctx.body = html
})

// Child route 2
let page = new Router()
page.get('/ 404'.async ( ctx )=>{
  ctx.body = '404 page! '
})
.get('/helloworld'.async ( ctx )=>{
  ctx.body = 'helloworld page! '
})

// Load all child routes
let router = new Router()
router.use('/', home.routes(), home.allowedMethods())
router.use('/page', page.routes(), page.allowedMethods())

// Load the routing middleware
app.use(router.routes()).use(router.allowedMethods())

app.listen(3000.() = > {
  console.log('Server started successfully')})Copy the code

The use of cookies

The CONTEXT of KOA (CTX) directly provides methods for reading and writing.

  • Ctx.cookie. get(name,[optins]): Reads cookies in context requests.
  • Ctx.cookie. set(name,value,[options]) : Writes cookies in context.

Write Cookie operation:

const Koa  = require('koa');
const app = new Koa();

app.use(async(ctx)=>{
    if(ctx.url=== '/index'){
        ctx.cookies.set(
            'MyName'.'FangC'
        );
        ctx.body = 'cookie is ok';
    }else{
        ctx.body = 'hello world'}}); app.listen(3000.() = > {
  console.log('Server started successfully')})Copy the code

Cookie options

For example, if we want to store the user name and retain the login status of the user, you can choose not to log in within 7 days, or choose not to log in within 30 days. This requires configuring some options on the write:

  • Domain: indicates the domain name of the cookie
  • Path: indicates the path where the cookie is written
  • MaxAge: indicates the maximum validity period of cookies
  • Expires: indicates the cookie expiration time
  • HttpOnly: Whether to obtain only from HTTP requests
  • Overwirte: Indicates whether overwriting is allowed
const Koa  = require('koa');
const app = new Koa();

app.use(async(ctx)=>{
    if(ctx.url=== '/index'){
        ctx.cookies.set(
            'MyName'.'FangC', {domain:'127.0.0.1'.// Write the domain name of the cookie
                path:'/index'.// Write the path to the cookie
                maxAge:1000*60*60*24.// Cookie validity period
                expires:new Date('2021-12-31'), // Cookie expiration time
                httpOnly:false.// Whether to obtain only in HTTP requests
                overwrite:false  // Whether overwriting is allowed}); ctx.body ='cookie is ok';
    }else{
        ctx.body = 'hello world'}}); app.listen(3000.() = > {
  console.log('Server started successfully')})Copy the code

Read the cookies:

const Koa  = require('koa');
const app = new Koa();

app.use(async(ctx)=>{
    if(ctx.url=== '/index'){
        ctx.cookies.set(
            'MyName'.'FangC', {domain:'127.0.0.1'.// Write the domain name of the cookie
                path:'/index'.// Write the path to the cookie
                maxAge:1000*60*60*24.// Cookie validity period
                expires:new Date('2021-12-31'), // Cookie expiration time
                httpOnly:false.// Whether to obtain only in HTTP requests
                overwrite:false  // Whether overwriting is allowed}); ctx.body ='cookie is ok';
    }else{
        if( ctx.cookies.get('MyName')){
            ctx.body = ctx.cookies.get('MyName');
        }else{
            ctx.body = 'Cookie is none'; }}}); app.listen(3000.() = > {
  console.log('Server started successfully')})Copy the code

Koa -static Static resource middleware

The installation

npm install --save koa-static
Copy the code

Create a new static folder and put images, CSS and JS files in the static folder.

use

const Koa = require('koa')
// Import the path package to concatenate paths
const path = require('path')
 // Import the koa-static package
const static = require('koa-static')

const app = new Koa()

// Static resource directory for relative entry file index.js path
const staticPath = './static'

// Open folder __dirname is the directory of the currently running file
app.use(static(
  path.join( __dirname,  staticPath)
))


app.use( async ( ctx ) => {
  ctx.body = 'hello world'
})

app.listen(3000.() = > {
  console.log('Server started successfully')})Copy the code

A template engine

It is not possible to write all the HTML code in JS during development, which is obviously not practical, nor is it possible to accomplish large-scale Web development. We have to borrow the templating mechanism to help us develop, and koA2’s templating mechanism relies on middleware for development.

Installing middleware

npm install --save koa-views
Copy the code

Install ejS template engine

npm install --save ejs
Copy the code

Ejs template engine installed, you can write templates, for unified template management, we create a new view folder, and under it a new index.ejs file.

Article Contents:

├── ├─ ├─ ├─ download.txt ├─ ├─ download.txtCopy the code

The view/index ejs file

<! DOCTYPEhtml>
<html>
<head>
    <title><%= title %></title>
</head>
<body>
    <h1><%= title %></h1>
    <p>EJS Welcome to <%= title %></p>
</body>
</html>
Copy the code

. / index. Js file

const Koa = require('koa')
const views = require('koa-views')
const path = require('path')
const app = new Koa()

// Load the template engine
app.use(views(path.join(__dirname, './view'), {
  extension: 'ejs'
}))

app.use( async ( ctx ) => {
  let title = 'hello koa2'
  await ctx.render('index', {
    title,
  })
})

app.listen(3000.() = >{
    console.log('Server started successfully');
})
Copy the code

reference

Koa Node.js series – using EJS template engine