This article mainly introduces a brief discussion of the asynchronous evolution history of Express. The editor thinks it is quite good. Now I will share it with you and give you a reference. Let’s follow the editor and take a look.
1. Introduction
In the world of Javascript, asynchronous (due to the single-threaded operation of JavaScript, So async in JavaScript can block) is everywhere.
Express is a very popular web server framework in the node environment. A large proportion of Node web applications use Express.
When using JavaScript to write server-side code, we will inevitably use asynchrony extensively. As JavaScript and Node evolve, our asynchronous processing methods will also evolve.
Next, let’s take a look at the evolution of asynchronous processing in Express.
2. Asynchronous processing of JavaScript
In the asynchronous world, we need to find a way to get the notification of the completion of the asynchronous method, then What are the methods in JavaScript?
2.1. Callback
Callback is the most original and oldest asynchronous notification mechanism in JS.
function asyncFn(callback) { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); callback(); // 发通知 }, 2000); } asyncFn(function () { console.log('我会在2s后输出'); });
2.2. Event monitoring
The function to obtain the result listens for a certain time. After the asynchronous method is completed, the event is triggered to achieve the notification effect.
2.3. Publish/Subscribe
Through the observer pattern, the publisher is modified when the asynchronous completion is completed. At this time, the publisher will notify the subscribers of the changes.
2.4. Promise
Promise is an improvement of the callback function. Using this, we can parallelize asynchrony and avoid callback hell.
function asyncFn() { return new Promise((resolve, reject) => { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); resolve(); // 发通知(是否有感觉到回调的影子?) }, 2000); }); } asyncFn() .then(function () { console.log('我会在2s后输出'); });
2.5. Generator
The Generator function is an asynchronous programming solution provided by ES6.
The following code is just a simple demonstration. In fact, the usage process of Generator is relatively complicated. This is another topic and will not be discussed in this article.
function asyncFn() { return new Promise((resolve, reject) => { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); resolve(); // 发通知(是否有感觉到回调的影子?) }, 2000); }); } function* generatorSync() { var result = yield asyncFn(); } var g = generatorSync(); g.next().value.then(()=>{ console.log('我会在2s后输出'); });
2.6, async...await
can be said to be the best solution for handling asynchronous in JavaScript.
function asyncFn() { return new Promise((resolve, reject) => { // 利用setTimeout模拟异步 setTimeout(function () { console.log('执行完毕'); resolve(); // 发通知(是否有感觉到回调的影子?) }, 2000); }); } async function run(){ await asyncFn(); console.log('我会在2s后输出'); } run();
3. Asynchronous processing in Express
In Express, what we generally use is The solution is: callback function, Promise, and async...await.
In order to build a demonstration environment, initialize an express project through express-generator. Generally, server-side projects use routes to call business logic. Therefore, we also follow this principle:
Open routs/index.js, we will see the following content, the following Demo will use this file for demonstration.
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router;
3.1. Callback function handles Express asynchronous logic
In Express, routing can load multiple middleware, so we Business logic can be written according to the writing method of middleware. In this way, asynchronous logic can be split very conveniently through layers of next.
var express = require('express'); var router = express.Router(); function asyncFn(req, res, next) { setTimeout(() => { req.user = {}; // 设置当前请求的用户 next(); }, 2000); } function asyncFn2(req, res, next) { setTimeout(() => { req.auth = {}; // 设置用户权限 next(); }, 2000); } function asyncFn3(req, res, next) { setTimeout(() => { res.locals = { title: 'Express Async Test' }; // 设置数据 res.render('index'); // 响应 }, 2000); } /* GET home page. */ router.get('/', asyncFn, asyncFn2, asyncFn3); // 一步步执行中间件 module.exports = router;
3.2. Promise processing Express asynchronous logic
In this solution, multiple business logics are packaged to return Promise function. Make combined calls through business methods to achieve the effect of one in and one out.
var express = require('express'); var router = express.Router(); function asyncFn(req, res) { return new Promise((resolve, reject) => { setTimeout(() => { req.user = {}; // 设置当前请求的用户 resolve(req); }, 2000); }); } function asyncFn2(req) { return new Promise((resolve, reject) => { setTimeout(() => { req.auth = {}; // 设置用户权限 resolve(); }, 2000); }); } function asyncFn3(res) { return new Promise((resolve, reject) => { setTimeout(() => { res.locals = { title: 'Express Async Test' }; // 设置数据 res.render('index'); // 响应 }, 2000); }); } function doBizAsync(req, res, next) { asyncFn(req) .then(() => asyncFn2(req)) .then(() => asyncFn3(res)) .catch(next); // 统一异常处理 }; /* GET home page. */ router.get('/', doBizAsync); module.exports = router;
3.3. async...await handles Express asynchronous logic
In fact, this solution also requires the support of Promise. It's just that the writing method is more intuitive and error handling is more direct.
It should be noted that Express is an early solution and does not have global error handling for async...await, so it can be processed using packaging.
var express = require('express'); var router = express.Router(); function asyncFn(req) { return new Promise((resolve, reject) => { setTimeout(() => { req.user = {}; // 设置当前请求的用户 resolve(req); }, 2000); }); } function asyncFn2(req) { return new Promise((resolve, reject) => { setTimeout(() => { req.auth = {}; // 设置用户权限 resolve(); }, 2000); }); } function asyncFn3(res) { return new Promise((resolve, reject) => { setTimeout(() => { }, 2000); }); } async function doBizAsync(req, res, next) { var result = await asyncFn(req); var result2 = await asyncFn2(req); res.locals = { title: 'Express Async Test' }; // 设置数据 res.render('index'); // 响应 }; const tools = { asyncWrap(fn) { return (req, res, next) => { fn(req, res, next).catch(next); // async...await在Express中的错误处理 } } }; /* GET home page. */ router.get('/', tools.asyncWrap(doBizAsync)); // 需要用工具方法包裹一下 module.exports = router;
4. Summary
Although koa has newer and better usage (koa is a generator , koa2 native async) supports better. But as someone who started working with node 0.x, I still have a special fondness for Express.
Some of the above solutions are no different from those used in koa. When combined with Express's huge ecosystem, they are even more powerful.
Github address of this article
The above is the detailed content of Express development history. For more information, please follow other related articles on the PHP Chinese website!