1. What is Koa?
Node.js is an asynchronous world. The official API supports the asynchronous programming model in the form of callback, which brings many problems, such as nesting of callback, and the possibility of calling callback to return data synchronously in asynchronous functions, which may bring inconsistency. Koa appears to solve the above problems.
Koa is the next generation web development framework based on Node.js platform.
Koa was built by Express's original team and is committed to becoming a smaller, more expressive and more robust Web framework. Using Koa to write web applications can avoid the tedious nesting of callback functions and greatly improve the efficiency of error handling. Koa does not bind any Middleware in the kernel method. It only provides a lightweight and elegant function library, which makes writing Web applications very handy. The development idea is similar to Express. The biggest feature is that asynchronous nesting can be avoided.
2. Installation and Use of Koa Framework
Install Node.js version 7.6 or more
Before using Koa2 to develop, Node.js was required. It required Node.js version to be higher than V7.6, because Node.js 7.6 version began to fully support async/await, so we can fully support Koa2.
(2) Installation of Koa
npm install --save koa or cnpm install --save koa with Taobao mirror
(3) Basic use of Koa
// Introducing Koa var koa = require('koa'); // Instantiation of Koa var app = new koa(); // Configuration routing app.use( async(ctx)=>{ ctx.body = "Hello,koa" }); // Monitor port app.listen(3000);
3. Use of Async, Await and Proise in Koa Asynchronous Processing
Async is to make the method asynchronous. When you execute this code with node in the terminal, you will find that Promise {'Hello async'} is output, which returns Promise.
async function testAsync(){ return 'Hello async'; }; const result = testAsync(); console.log(result); // Promise { 'Hello async' }
Await is waiting for the async method to complete. Actually, await waits for only an expression, which in the official document refers to Promise objects, but it also accepts normal values. Note: await must be used in the async method, because the await access itself causes the program to stop blocking, so it must be used in the asynchronous method.
function getData() { return 'This is data'; }; async function testAsync() { return 'Hello async'; }; async function test() { // await returns a normal value const v1 = await getData(); console.log(v1); // This is data // await returns promise object const v2 = await testAsync(); console.log(v2); // Hello async }; test();
To sum up, async is used to declare that a function is asynchronous. It encapsulates the return value of a subsequent function as a Promise object, while await is used to wait for an asynchronous method, Promise, to complete and return the result of its solution.
4. Use of Koa Routing
Routing in Koa is different from Express, which can be configured by introducing Express directly. But in Koa, we need to install the corresponding koa-router routing module.
// 1. Install npm install --save koa-router var Koa = require('koa'); // 2. Introducing routing and instantiating var router = require('koa-router')(); var app = new Koa(); // 3. Configuring routing // Unlike Express, req and res, all information is put in ctx router.get('/', async (ctx) => { // Return data // It is equivalent to res.write() and res.end() in native Node.js. ctx.body = "home page"; }); // 4. Start routing (from official documents); // router.allowedMethods() can be configured or not. // If the response header is not set before, the response header can be set automatically after configuring this option. app.use(router.routes()).use(router.allowedMethods()); // Monitor port app.listen(3000);
In addition, Koa's routing execution order is different from Express's. Koa chooses the onion ring model, which is the last response of the code after next() in the first route accessed.
The following code will be output in numbered order to illustrate the order in which the routing is executed.
var Koa = require('koa'); var router = require('koa-router')(); var app = new Koa(); app.use(async (ctx, next) => { console.log('1.This is a middleware 01'); await next(); console.log('5.After matching the routing, it will return to execute the middleware.') }); app.use(async (ctx, next) => { console.log('2.This is a middleware 02'); await next(); console.log('4.After matching the routing, it will return to execute the middleware.') }); router.get('/news', async (ctx) => { console.log('3.Match up to news This routing'); ctx.body = 'News page' }); app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
5.Koa Middleware
Middleware is a series of operations completed with routing matching. We can call it middleware. Using Middleware in Koa can achieve the following functions:
(1) Adding applications. app.use() is the main function to add or start some applications, such as the common use of third-party middleware.
var Koa = require('koa'); var router = require('koa-router')(); var app = new Koa(); // Koa Application Level Middleware app.use(async (ctx, next) => { // Print the date before matching the route console.log(new Date()); // Continue downward matching after the current routing matching is completed // If you don't write next(), the route is matched and terminated. await next(); }); router.get('/news', async (ctx) => { ctx.body = 'News page' }); // Start routing; // router.allowedMethods() can be configured or not // If no response header has been set before, the response header can be set automatically after configuring this option. app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
(2) Matching routing. Multi-level routing matching is accomplished mainly through next().
var Koa = require('koa'); var router = require('koa-router')(); var app = new Koa(); // Koa Routing Level Middleware // Configuration of news pages router.get('/news', async(ctx,next) => { console.log('This is news routing.'); // Continue downward matching after matching to routing await next(); }); // Configuration of news pages router.get('/news', async (ctx) => { ctx.body = 'This is the news page.' }); app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
(3) Error handling. If the current access path is not matched downwards, the error response can be given through the middleware.
var Koa = require('koa'); var router = require('koa-router')(); var app = new Koa(); // Koa error handling Middleware // Whether app.use is placed before or after routing // They all execute app.use before routing app.use(async (ctx, next) => { console.log('This is a middleware'); // Execution order 1 await next(); if (ctx.status == 404) { // Execution order 3 ctx.body = 'This is a 404 page.'; } else { console.log(ctx.url); } }); // Configure news page//execution order 2 router.get('/news', async (ctx, next) => { console.log('This is news routing.'); await next(); }); app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
6. Get transfer value and get get transfer value in Koa.
There are two main ways to get values in Koa:
(1) Key-value pair splicing is used to transfer parameters. The receiving parameters are mainly obtained by ctx.qruery. It should be noted that the same results can be obtained in CTX and ctx.request.
var Koa = require('koa'); var router = require('koa-router')(); var app = new Koa(); // http://localhost:3000/news_details?id=123&author=aiguangyuan router.get('/news_details',async(ctx)=>{ // Reading Get Transfer Value from ctx console.log(ctx.url); // /news_details?id=123&author=aiguangyuan console.log(ctx.query); // { id: '123', author: 'aiguangyuan' } // Getting objects is the most common way console.log(ctx.querystring) // id=123&author=aiguangyuan // What you get is a string // Get the Get pass-through value from the request in ctx console.log(ctx.request.url); // /news_details?id=123&author=aiguangyuan console.log(ctx.request.query); // { id: '123', author: 'aiguangyuan' } console.log(ctx.request.querystring); // id=123&author=aiguangyuan ctx.body='News Details Page'; }); app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
(2) Dynamic routing and receiving parameters are mainly obtained by ctx.params.
var Koa = require('koa'); var router = require('koa-router')(); var app = new Koa(); // http://localhost:3000/news_details/123/456 router.get('/news_details/:aid/:cid', async (ctx) => { // Getting the transfer value of dynamic routing console.log(ctx.params); // { aid: '123' ,cid:'456'} ctx.body = 'News Details Page'; }); app.use(router.routes()); app.use(router.allowedMethods()); app.listen(3000);
7. Getting the post value in Koa.
There are two main ways of post ing in Koa:
(1) Encapsulation of a native method for obtaining post parameters.
// Encapsulation method for obtaining post parameters exports.getPostData = function (ctx) { // Getting asynchronous data return new Promise(function (resolve, reject) { try { let str = ''; ctx.req.on('data', function (chunk) { str += chunk; }); ctx.req.on('end', function (chunk) { resolve(str); }); } catch (err) { reject(err); } }) };
Introduce encapsulation method to obtain data.
var Koa = require('koa'); var router = require('koa-router')(); // Method of introducing encapsulation var common = require('./module/common.js') var app = new Koa(); // Receiving data submitted by post router.post('/doAdd', async (ctx) => { // Data acquisition by encapsulation var data = await common.getPostData(ctx); console.log(data); // username=aiguangyuan&password=123456 ctx.body = 'Add success'; }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);
(2) Use body-parser middleware to get post data.
// 1. Install NPM install -- save koa-body parser; var Koa = require('koa'); var router = require('koa-router')(); // 2. Introducing Middleware var bodyParser = require('koa-bodyparser'); var app = new Koa(); // 3. Configuring the middleware of body parser app.use(bodyParser()); router.post('/doAdd', async (ctx) => { // 4. Obtain form submission data through ctx.request.body ctx.body=ctx.request.body; // {"username":"aiguangyuan","password ":"123456"} }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);
8. Use of Cookie in Koa
Cookie is saved in the browser client, which allows us to share data when the same browser accesses the same domain name. It can achieve the following functions.
(1). Save user information
(2) Browser history information
(3). Guess what you like about functions
(4) 10 days free of landing
(5) Data transfer between multiple pages
(6).cookie realizes shopping cart function
var Koa = require('koa'); var router = require('koa-router')(); var app = new Koa(); router.get('/', async (ctx) => { // Note that cookie s in koa cannot be set directly into Chinese // Using Buffer to Solve the Chinese Problem of Setting up cookie s var userinfo = new Buffer('Zhang San').toString('base64'); // 1. Setting cookie s ctx.cookies.set('userinfo',userinfo ,{ // Set the number of milliseconds that have expired maxAge: 60 * 1000 * 60, // The following parameters are not commonly used // Specific expiration time expires: '2019-1-1', // The path that cookie s can access by default is'/' path: '/', // The domain name that cookie s can access by default is all pages under the current domain name, unless there are multiple subdomains. domain: '', // Secure cookie, default false, set to true to indicate that only https can access it secure: false, // Is it just a server accessible cookie? The default is true httpOnly: true, // Whether to overwrite, default to false, not often used overwrite: false }); ctx.body = "This is the front page."; }); // Accessing cookie s in another route router.get('/content', async (ctx) => { // 2. Get the set cookie and convert the cookie var data = ctx.cookies.get('userinfo'); var userinfo = new Buffer(data,'base64').toString(); console.log(userinfo); // Zhang San ctx.body = 'This is the content page.' }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);
9. Use of Session in Koa
session is a mechanism for recording customer status. Compared with cookie s, they differ mainly in the following aspects:
(1) cookie data is stored on the client's browser and session data on the server.
(2) cookies are not very secure. Others can analyze cookies stored locally and cheat cookies. Considering security, session should be used.
(3) Session will be saved on the server for a certain period of time. When access increases, it will occupy the server. Considering the performance, cookie should be used.
(4) Data stored by a single cookie cannot exceed 4K, and many browsers limit a site to a maximum of 20 cookies.
// 1.npm install koa-session --save var Koa = require('koa'); var router = require('koa-router')(); // 2. Introducing koa-session var session = require('koa-session'); var app = new Koa(); // 3. Set the signature of cookie, you can set or default app.keys=['some secret hurr']; // 4. Configuring session Middleware var CONFIG = { key:'koa:sess', // cookie key (default) maxAge:8600000, // Cook expiration time (modification) overwrite:true, // Can override override (default) httpOnly:true, // Is it available only to the server (default) signed:true, // Signature (default) rolling:false, // Update session every time you visit (default) renew:true // Update session near expiration time }; // 5. Enabling Middleware app.use(session(CONFIG,app)); router.get('/login', async (ctx) => { // Setting session ctx.session.userinfo = 'Zhang San'; ctx.body = "This is the login page."; }); router.get('/', async (ctx) => { // Get session var userinfo = ctx.session.userinfo; console.log(userinfo); // Zhang San ctx.body = 'This is the front page.' }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);
10. Acquisition of static resources in Koa
The static resource response in Koa is mainly realized through the middleware of Koa-static.
// 1.npm install koa-static --save var Koa = require('koa'); var Router = require('koa-router'); var views = require('koa-views'); // 2. Introducing middleware for handling static resources var static = require('koa-static'); var app = new Koa(); var router = new Router(); app.use(views('views', { extension: 'ejs' })); app.use(bodyParser()); // 3. Configuring the middleware of static web services; // You can write more than one, find it in different directories app.use(static(__dirname+'/static')); app.use(static(__dirname+'/public')); router.get('/', async (ctx) => { await ctx.render('login'); }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);
11. Using Ejs Template Engine in Koa
Ejs is a JavaScript template engine, which is used to render the database query data to the template and realize a dynamic website.
// 1.npm install koa-views --save // 2.npm install ejs --save var Koa = require('koa'); var router = require('koa-router')(); // 3. Introducing koa-views var views = require('koa-views'); var app = new Koa(); // 4. Configuring Template Engine Middleware // The first parameter in views is the location of the template file app.use(views('views', { // Using EJS template engine, template file ends with EJS extension: 'ejs' })); // It is also possible to configure the template engine in the following way // app.use(views('views',{ // Template files end in html // map:{ html:'ejs'} // })); // If we need to render a common data in every render of the route // Common data needs to be placed in middleware so that it can be used anywhere in the template app.use(async(ctx,next)=>{ // userinfo can be used in any route ctx.state.userinfo ='Li Si'; await next() }); // Configure news page routing router.get('/news', async (ctx) => { // Simulate the data from the database let list = [ 'Xi Da delivered a speech', 'Trump made a speech', 'Li Keqiang delivered a speech' ]; let content="<h2>This is a H2</h2>"; let num = 100; // 5. Rendering static pages await ctx.render('news', { list:list, content:content, num:num }); }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);
The common grammar of Ejs is as follows:
<!-- 1.Introducing Public Documents --> <% include public/header.ejs%> <!-- 2.Cyclic Rendering Data --> <ul> <%for(var i=0;i<list.length;i++){%> <li><%=list[i]%></li> <%}%> </ul> <!-- 3.binding html data,No resolution --> <%=content%> <!-- 4.Rendering html Data and parsing --> <%-content%> <!-- 5.Conditional judgement --> <% if(num==100){ %> <p>The current number equals 100</p> <% }else{ %> <p>The current number is not equal to 100</p> <% } %> <!-- 6.Rendering all routing common data --> <p><%=userinfo %></p>
12.Koa uses the Art-template template engine
Art-template is a simple, ultra-fast template engine. It optimizes the rendering speed of templates by using scope pre-declaration technology to achieve performance close to the JavaScript limit, while supporting NodeJS and browsers. Art-template supports Ejs grammar, and can also use a grammar similar to Angular data binding.
// 1. Installation module // npm install --save art-template // npm install --save koa-art-template var Koa = require('koa'); var router = require('koa-router')(); var path = require('path'); // 2. Introducing Modules var render = require('koa-art-template'); var app = new Koa(); // 3. Configuration module render(app, { // Position of View root: path.join(__dirname, 'views'), // Suffix name extname: '.html', // Whether to turn on debugging mode debug: process.env.NODE_ENV !== 'production' }); router.get('/detail', async (ctx) => { // Simulate the data obtained from the database let data = { name: 'Li Si' }; let text = '<span>This is a text.</span>'; let num = 10; let list = ['List item 1','List item 2','List item 3']; // 4. Rendering data await ctx.render('detail', { data:data, text:text, num:num, list:list }) }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3000);
Ejs Writing of Art-template Template Engine.
<h1>Art-template Template Engine Ejs Writing method</h1> <h2>1.Binding data</h2> <span><%=data.name %></span> <span><%=1+2 %></span> <h2>2.binding html data</h2> <span><%-text%></span> <h2>3.conditional rendering</h2> <% if(num>10){ %> <span>Size 10</span> <% }else{ %> <span>Less than 10</span> <%}%> <h2>4.Circular data</h2> <% for(var i=0;i<list.length;i++){ %> <p> <%=i%>--<%=list[i]%> </p> <%}%> <h2>5.Template introduction</h2> <% include('./public/footer.html') %>
Angular Writing of Art-template Template Engine.
<h2>Art-template Template Engine Angular Writing method</h2> <h2>1.Binding data</h2> <span>{{data.name}}</span> <span>{{1+2}}</span> <h2>2.binding html data</h2> <span>{{@text}}</span> <h2>3.conditional rendering</h2> {{ if num>10 }} <span>Size 10</span> {{else}} <span>Less than 10</span> {{/if}} <h2>4.Circular data</h2> {{each list}} <p> {{$index}}--{{$value}} </p> {{/each}} <h2>5.Template introduction</h2> {{ include 'public/footer.html' }}
13. The use of Koa-multer, the middleware of Koa file upload
// 1.npm install koa-multer --save // 2. Introducing koa-multer const multer = require('koa-multer'); const router = require('koa-router')(); // 3. Configure koa-multer; var storage = multer.diskStorage({ // File save path destination: function (req, file, cb) { // Note that the path must exist cb(null, 'public/uploads') }, // Modify the file name filename: function (req, file, cb) { var fileFormat = (file.originalname).split("."); // Picture name drops out after adding timestamp cb(null, Date.now() + "." + fileFormat[fileFormat.length - 1]); } }); // 4. Load configuration var upload = multer({ storage: storage }); // 5. Using upload, upload.single() stands for upload single, and the parameter is the name value of upload input. router.post('/doAdd', upload.single('input-name-value'), async (ctx, next) => { ctx.body = { // Return file name filename: ctx.req.file.filename, body: ctx.req.body } });
If you want to use a routing, so that multiple places share uploaded pictures, the routing can be configured as follows.
router.post('/doAdd', upload.fields([ { // Upload form input value name: 'avatar', // Number maxCount: 1 }, { name: 'cover', maxCount: 2 } ]), async (ctx, next) => { console.log(ctx.request.files); console.log(ctx.files); ctx.body = 'Upload success!'; } );
Notice that the form form is added with enctype="multipart/form-data"
13.Koa operates MySQL database
MySQL module is the engine for Node to operate MySQL. It can build tables, add, delete, change and check MySQL database in Node.js environment.
// 1.npm install --save mysql // 2. Introducing Modules const mysql = require('mysql'); // 3. Connecting to the database const connection = mysql.createConnection({ host: '127.0.0.1', // Database Address user: 'root', // User name password: '123456' , // Password database: 'my_data' // Database name }) // 4. Execute sql statement to operate database connection.query('SELECT * FROM user', (error, results, fields) => { if (error) { console.log(error) }; // Operational data // Closing session connection.release(); });
Note that after the database session operation is completed, it needs to be closed to avoid occupying connection resources.
When multiple sessions need to operate on the database, in order to avoid reconnecting each session, a connection pool is needed to manage the session.
// 1.npm install --save mysql // 2. Introducing Modules const mysql = require('mysql'); // 3. Creating data pools const pool = mysql.createPool({ host: '127.0.0.1', // Database Address user: 'root', // User name password: '123456', // Password database: 'my_data' // Database name }) // 4. Session operation in data pool pool.getConnection(function (err, connection) { // 5. Execute sql statement to operate database connection.query('SELECT * FROM user', (error, results, fields) => { // Execution operation // Release connection connection.release(); // If there is a mistake, throw it if (error) { throw error; } }) })
14.Koa operates MongoDB database
MongoDB is a product between relational database and non-relational database, which has the most abundant functions and resembles relational database. The data structure he supports is very loose, so it can store more complex data types. Mongo's greatest feature is that the query language he supports is very powerful. Its grammar is somewhat similar to object-oriented query language. It can almost achieve most functions similar to single-table query in relational databases, and it also supports data indexing. It is characterized by high performance, easy deployment, easy use, and very convenient storage of data.
// 1.npm install mongodb --save // 2. Introduce MongoClient under mongodb var MongoClient = require('mongodb').MongoClient; // 3. Define the address of the database connection and configure the database var url = 'mongodb://localhost:27017/'; var dbName = 'koa'; // 4. Connecting to the database MongoClient.connect(url, function (err, client) { const db = client.db(dbName); }); // 5. Operating database MongoClient.connect(url, function (err, db) { db.collection('user').insertOne({ "name": "Lucy" },function (err, result){ // Judge whether the addition is successful // close database db.close(); }) })