Koa2 usingasyncandawaitTo handle asynchrony, the use function of the KOA2 instance takes middleware arguments.

Let’s start with a small core demo of KOA2

// Middleware repository
const arr = [
        async (next) => {
            console.log(1);
            await next();
            console.log(2);
        },
        async (next) => {
            console.log(3);
            await new Promise((resolve, reject) = > {
                setTimeout(() = > {
                    resolve(
                        console.log(4)); },1000);
            }); // The asynchronous operation await the following promise resolve before proceeding
            await next();
            console.log(5);
        },
        async (next) => {
            console.log(6);
        },
        async (next) => {
            // Will not be executed because next was not executed in the previous function
            console.log(7);
            await next();
            console.log(8);
        },
        async (next) => {
            // Will not be executed because next was not executed in the previous function
            console.log(9); }];function fun(arr) {
        function dispose(index) {
            const currentFun = arr[index];
            const next = dispose.bind(null, index + 1);
            return currentFun(next); / / tail recursion
        }

        dispose(0);
    }

    fun(arr); // Prints 1, 3, 1 second and 4, 6, 5, 2
Copy the code

Start code (create a new ware.js file)

const http = require('http');
const urlParser = require("url"); // Parse the URL string and the URL object

class Middleware {
    constructor() {
        this.wares = [];  // Storage middleware
    };

    use(fun) {
        this.wares.push(fun); // Collect middleware
        return this;
    };

    /* The core of middleware processing */
    handleMiddleware(wareList) {
        return function (ctx) {
            // Middleware call
            function dispose(index) {
                const currentFun = wareList[index];
                try {
                    // Wrap currentFun with promise.resolve to prevent currentFun from being passed in as a normal function
                    return Promise.resolve(
                        /* Dispose. Bind (null, index + 1) will not fetch the next middleware */
                        currentFun(ctx, dispose.bind(null, index + 1))); }catch (e) {
                    return Promise.reject(e); }}// Execute the first middleware of the repository immediately
            dispose(0); }};createContext(req, res) {
        const {method, url} = req;
        const {query} = urlParser.parse(url, true);

        / /... It's a lot more complicated than that, so we're just going to do a simple package
        return {
            method, url, query,
            res
        };
    }

    serverHandle() {
        return (req, res) = > {
            // We trigger the middleware when the request comes in
            const fn = this.handleMiddleware(this.wares);
            // Get the context object for the current request
            const ctx = this.createContext(req, res); fn(ctx); }};listen(. args) {
        const app = http.createServer(this.serverHandle()); // This is just to simulate getting an HTTP serviceapp.listen(... args);// Directly to Node's native HTTP module
    };
}

module.exports = Middleware;
Copy the code

Test (create a new demo.js file in the same directory)

const Demo = require("./ware");

const app = new Demo();

app.use(async (ctx, next) => {
    await next();
    console.log(`${ctx.method} ${ctx.url}`);
});

app.use(async ctx => {
    ctx.res.end("hello world")}); app.listen(5000.() = > {
    console.log("http://localhost:5000");
});
Copy the code

> run CMDnode demo.jsBrowser accesshttp://localhost:5000= >hello world.