let http = require('http')
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'})
  response.end('Hello World')
}).listen(8081, () = > {console.log('Server running at http://127.0.0.1:8081/)})Copy the code

This is how the HTTP core module of Node is used. Koa solves three problems of the HTTP module

Problems with native HTTP modules

  • A flaw in the way the code is written, where all the logic is coupled in one function
  • Req and RES are weak
  • HTTP cannot uniformly handle errors based on callbacks

Koa’s answer

The middleware

  • By constructing middleware to slice logic, async function is used to make asynchronous code have synchronous writing mode

  • Koa middleware has a classic Onion model

Requests pass through the outer middleware to the inner middleware and back to the outer, similar to DOM event capture and bubbling.

Each layer is an async function so each layer has the ability to wait for the lower layer middleware to finish before continuing, of course you need to make sure you write await before next(), otherwise the layer will continue without waiting for the lower layer.

Since each layer is a function, it is easy to build the Onion model, with functions within functions, passing the lower middleware to the upper middleware, which calls it.

use(callback) { // Register middleware
    this.middlewares.push(callback)
}
compose(ctx) { // Build the onion model
    // Link multiple promises together to form a promise chain
    const dispatch = i= > {
        if (i === this.middlewares.length) return Promise.resolve()
        let middleware = this.middlewares[i]
        // Pass the lower level middleware to the upper level middleware via deferred call functions
        return Promise.resolve(middleware(ctx, () => dispatch(i+1)))}return dispatch(0)}Copy the code

Extend REQ and RES

Koa instances rely on request, Response, and Context extension objects, and each Koa instance maintains a separate extension object

Request is an extension to REq, Response is an extension to RES, and the context object proxies some functions of Request and Response

Each request also maintains a separate extension object

  createContext(req, res) { // Build CTX by extending reQ and RES functionality
    // Ensure that no context is shared on each request
    let ctx = Object.create(this.context)
    let _request = Object.create(this.request)
    let _response = Object.create(this.response)
    
    ctx.request = _request
    ctx.req = ctx.request.req = req
    ctx.response = _response
    ctx.res = ctx.response.res = res
    return ctx
  }
Copy the code

What does it extend, for example, ctx.url

/*context*/
module.exports = {
  get url() {
      return this.request.url
  }
}
Copy the code
/*request*/
module.exports = {
    get url() {
        return this.req.url
    }
}
Copy the code

Request acts as a layer 1 proxy to extend REQ, and context acts as a layer 2 proxy to get extensions on Request and Response

Unified handling of errors based on the event module

Koa inherits the Emitter (Events) module in Node, which has the function of publishing and subscribling.it can publish error events and monitor them