Koa is a very lightweight Web framework with nothing in it but CTX and Middleware, and even the most basic router functions need to be implemented by installing other middleware. It's simple, but it's powerful enough that you can build complete Web services just by relying on middleware mechanisms. The koA source code is also very concise, the base code is less than 2000 lines, very suitable for reading and learning.
The source code for KOA is directly available on Github. This article uses the latest version 2.5.1.
When I first saw the source code for KOA, I was really confused. After repeatedly checking that I had read it correctly, I was convinced that there were only four koA source files -- application.js, Context.js, request.js, response.js, which were located in the project's lib folder. And you can almost guess what each file is for by looking at the file name. The next step is to open it and see what's inside.
Js is an entry file, which is an Application class inherited from the Emitter class in the Event module. This is where we defined the app instance we created when using KOA.
To analyze a class, you start by looking at its constructor, which defines an array of Middleware, and three properties: Context, Request, and Response, which are defined in three other files. Instead of looking at the other files, think about when we were using KOA. After we created the app instance, the next step was to use various middleware, so let's look directly at the Use method.
Use receives a middleware function as an argument, does type verification first, and if it is passed a generator, koA2 converts it first with convert (this is for KOA1 compatibility, removed later versions), and does only one thing in the end. Push this function into the Middleware array. The use method finally returns this, which is the KOA instance itself, which means we can implement chained calls.
Set up the middleware, we start the KOA service last step is to call the listen method to set up the listening port, next we will look at the implementation of listen method. Listen is much simpler. It's only two lines long, but you don't do anything else. You just call the createServer method under node's native HTTP module to create the service, and listen sets up the listener, and that's it. As we all know, HTTP createServer needs to pass in a function that koA returns by calling the callback method.
The callback first uses compose to turn all middleware into a function (the implementation of Compose will also be discussed in detail later). It calls the Emitter listenerCount method to determine whether there are listeners for error events. If the default event-listening method onError is not registered for error events, then it is time to define the function we want to pass into createServer. This function takes req and res, and koA does something to it: The reQ and RES are wrapped into the familiar CTX object by calling the createContext method (what createContext does next), and then CTX and the middleware function fnMiddleware that we handled earlier are passed into the handleRequest method.
In handleRequest, first fetch res, first set the status to 404, then register the success and failure status methods after executing the middleware, call ctx. onError when the failure to catch the exception, call the success respond method to respond the result. The onFinished module is used again. OnFinished ensures that a stream will execute a callback when it closes, completes, and reports an error, passing in our exception handler to handle the error message. The respond method, on the other hand, reads the CTX message, writes the data to the RES and responds to the request. At this point, the whole process is complete.
CreateContext creates three objects, Context, Request, and Response, and then attaches the various objects to the context, so that we can retrieve the req, RES, and other information from the CTX. The context, Request, and Response objects are created using the three objects in the current app class, which are created by importing objects from three external files, so let's look at what's in those three files.
All three files export objects. In the context, only basic methods are defined, and the rest of the property methods are delegated to the Request and response properties. We already know that the request and response on the context are created from objects in the other two files. The contents of these two files are more concise. They are properties and methods that we access when we use them, and they encapsulate the actual request and response operations by controlling the REq and RES in getters and setters. This completes the entire koA core of four files.
The result is a function called fnMiddleware, which also has context and next parameters and uses index variables to record which middleware it is currently processing. Then call the Dispatch method from the first. The relationship between the current passed parameter and index is determined. If next is called several times within a middleware, the parameter will be smaller than index, and an error will be reported. After the current middleware to withdraw from an array, each CTX and next to it during the next call dispatch, the parameters for the next place, this will add the middleware in order to come in, finally when I equal to the middleware array length, which is no other middleware, then perform incoming next parameters at the beginning, If fn does not exist, return an empty promise. When the central execution is finished, that is, the next execution of the previous middleware is finished, it will naturally trigger "await" execution downward, and then the execution rights will be returned in reverse order. The final combination result is first from outside to inside, and then from inside to outside, which is the well-known onion circle model.
Koa's error handling mechanism is also very special, we just listen for koA instances of error events, all errors can be handled uniformly. As mentioned earlier, a failed call to fnMiddleware will be caught by a unified onError method that corresponds to the ONError method on CTX. Let's take a look at the implementation. The very important line is this.app.emit('error', err, this); Since our KOA inherits from event, we can send an error event, which we just need to handle. In the previous middleware processing, errors are rejected and naturally caught by a catch.
Above, is the basic koA core module flow, the principle is very simple, but with a variety of middleware, KOA can fully achieve a functional Web server.
This article is original, willing to share but reprint please inform in advance, more articles to view my home page, thank you for reading, such as error welcome correction.