Let Express support async method sharing
This article mainly introduces in detail how to make Express support async/await. The editor thinks it is quite good, so I will share it with you now and give it as a reference. Let’s follow the editor to take a look, I hope it can help everyone.
With the release of Node.js v8, Node.js has natively supported async/await functions, and the web framework Koa has also released the official version of Koa 2, which supports async/await middleware. Handling asynchronous callbacks brings great convenience.
Since Koa 2 already supports async/await middleware, why not use Koa directly, but also modify Express to support async/await middleware? Because the official version of Koa 2 was released not long ago, and many old projects still use Express, it is impossible to overthrow them and rewrite them in Koa. This cost is too high, but if you want to use the convenience brought by the new syntax, you can only Express has been transformed, and this transformation must be non-intrusive to the business, otherwise it will cause a lot of trouble.
Use async/await directly
Let us first look at the situation of using async/await function directly in Express.
const express = require('express'); const app = express(); const { promisify } = require('util'); const { readFile } = require('fs'); const readFileAsync = promisify(readFile); app.get('/', async function (req, res, next){ const data = await readFileAsync('./package.json'); res.send(data.toString()); }); // Error Handler app.use(function (err, req, res, next){ console.error('Error:', err); res.status(500).send('Service Error'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
The above does not modify Express, and directly uses the async/await function to process the request. When requesting http://127.0.0.1:3000/, it is found that the request can be requested normally, and the response can also be responded normally. . It seems that you can use the async/await function directly without making any changes to Express. But if an error occurs in the async/await function, can it be handled by our error handling middleware? Now let's read a non-existing file, for example, replace the previously read package.json with age.json.
app.get('/', async function (req, res, next){ const data = await readFileAsync('./age.json'); res.send(data.toString()); });
Now when we request http://127.0.0.1:3000/, we find that the request cannot be responded to and will eventually time out. The following error was reported in the terminal:
It was found that the error was not handled by the error handling middleware, but an unhandledRejection exception was thrown. Now if we use try/ catch to manually catch errors?
app.get('/', async function (req, res, next){ try { const data = await readFileAsync('./age.json'); res.send(datas.toString()); } catch(e) { next(e); } });
It is found that the request is processed by the error handling middleware, which means that it is okay for us to manually and explicitly capture the error, but it is too inconvenient to add a try/catch to each middleware or request processing function. It is elegant, but it is intrusive to the business code, and the code also looks ugly. Therefore, through experiments using async/await functions directly, we found that the direction of transformation of Express is to be able to receive errors thrown in async/await functions without being intrusive to business code.
Modify Express
There are two ways to handle routing and middleware in Express. One is to create an app through Express, add middleware and handle routing directly on the app, as shown below Like this:
const express = require('express'); const app = express(); app.use(function (req, res, next){ next(); }); app.get('/', function (req, res, next){ res.send('hello, world'); }); app.post('/', function (req, res, next){ res.send('hello, world'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
The other is to create a routing instance through the Router of Express. Add middleware and process routing directly on the routing instance, like the following:
const express = require('express'); const app = express(); const router = new express.Router(); app.use(router); router.get('/', function (req, res, next){ res.send('hello, world'); }); router.post('/', function (req, res, next){ res.send('hello, world'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
These two methods can Mix it up. Now let's think about how to make a function like app.get('/', async function(req, res, next){}) so that the errors thrown by the async function inside can be handled uniformly. Woolen cloth? In order for errors to be handled uniformly, of course, next(err) must be called to pass the error to the error handling middleware. Since the async function returns a Promise, it must be in the form of asyncFn().then().catch. (function(err){ next(err) }), so if you modify it like this, you will have the following code:
app.get = function (...data){ const params = []; for (let item of data) { if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') { params.push(item); continue; } const handle = function (...data){ const [ req, res, next ] = data; item(req, res, next).then(next).catch(next); }; params.push(handle); } app.get(...params) }
In the above code, we judge that the parameters of the app.get() function , if there is an async function, use item(req, res, next).then(next).catch(next); to handle it, so that errors thrown in the function can be captured and passed to the error handling middleware. . However, there is an obvious mistake in this code. It calls app.get() at the end, which is recursive, destroys the function of app.get, and cannot handle the request at all, so it needs to continue to be modified.
We said before that Express's two ways of handling routing and middleware can be mixed, so we will mix these two ways to avoid recursion. The code is as follows:
const express = require('express'); const app = express(); const router = new express.Router(); app.use(router); app.get = function (...data){ const params = []; for (let item of data) { if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') { params.push(item); continue; } const handle = function (...data){ const [ req, res, next ] = data; item(req, res, next).then(next).catch(next); }; params.push(handle); } router.get(...params) }
It seems that after the transformation like above Everything is working properly and requests are being processed normally. However, by looking at the source code of Express, I found that this destroyed the app.get() method, because app.get() can not only be used to process routing, but also be used to obtain the application configuration. The corresponding source code in Express is as follows:
methods.forEach(function(method){ app[method] = function(path){ if (method === 'get' && arguments.length === 1) { // app.get(setting) return this.set(path); } this.lazyrouter(); var route = this._router.route(path); route[method].apply(route, slice.call(arguments, 1)); return this; }; });
So during transformation, we also need to do special processing for app.get. In actual applications, we not only have get requests, but also post, put and delete requests, so our final modified code is as follows:
const { promisify } = require('util'); const { readFile } = require('fs'); const readFileAsync = promisify(readFile); const express = require('express'); const app = express(); const router = new express.Router(); const methods = [ 'get', 'post', 'put', 'delete' ]; app.use(router); for (let method of methods) { app[method] = function (...data){ if (method === 'get' && data.length === 1) return app.set(data[0]); const params = []; for (let item of data) { if (Object.prototype.toString.call(item) !== '[object AsyncFunction]') { params.push(item); continue; } const handle = function (...data){ const [ req, res, next ] = data; item(req, res, next).then(next).catch(next); }; params.push(handle); } router[method](...params); }; } app.get('/', async function (req, res, next){ const data = await readFileAsync('./package.json'); res.send(data.toString()); }); app.post('/', async function (req, res, next){ const data = await readFileAsync('./age.json'); res.send(data.toString()); }); router.use(function (err, req, res, next){ console.error('Error:', err); res.status(500).send('Service Error'); }); app.listen(3000, '127.0.0.1', function (){ console.log(`Server running at http://${this.address().address }:${this.address().port }/`); });
Now the transformation is complete, we only need to add a small piece of code, You can directly use async function as the handler to handle requests, which is not intrusive to the business. The thrown errors can also be passed to the error handling middleware.
Related recommendations:
NodeJs’s method of handling asynchronous processing through async and await
How to use async functions in Node.js
Detailed explanation of ES6's async+await synchronization/asynchronous solution
The above is the detailed content of Let Express support async method sharing. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Quark Netdisk and Baidu Netdisk are very convenient storage tools. Many users are asking whether these two softwares are interoperable? How to share Quark Netdisk to Baidu Netdisk? Let this site introduce to users in detail how to save Quark network disk files to Baidu network disk. How to save files from Quark Network Disk to Baidu Network Disk Method 1. If you want to know how to transfer files from Quark Network Disk to Baidu Network Disk, first download the files that need to be saved on Quark Network Disk, and then open the Baidu Network Disk client. , select the folder where the compressed file is to be saved, and double-click to open the folder. 2. After opening the folder, click "Upload" in the upper left corner of the window. 3. Find the compressed file that needs to be uploaded on your computer and click to select it.

1. First, we enter NetEase Cloud Music, and then click on the software homepage interface to enter the song playback interface. 2. Then in the song playback interface, find the sharing function button in the upper right corner, as shown in the red box in the figure below, click to select the sharing channel; in the sharing channel, click the "Share to" option at the bottom, and then select the first "WeChat Moments" allows you to share content to WeChat Moments.

async is es7. async and await are new additions to ES7 and are solutions for asynchronous operations; async/await can be said to be syntactic sugar for co modules and generator functions, solving js asynchronous code with clearer semantics. As the name suggests, async means "asynchronous". Async is used to declare that a function is asynchronous; there is a strict rule between async and await. Both cannot be separated from each other, and await can only be written in async functions.

How to handle file upload? The following article will introduce to you how to use express to handle file uploads in the node project. I hope it will be helpful to you!

Recently, Baidu Netdisk Android client has ushered in a new version 8.0.0. This version not only brings many changes, but also adds many practical functions. Among them, the most eye-catching is the enhancement of the folder sharing function. Now, users can easily invite friends to join and share important files in work and life, achieving more convenient collaboration and sharing. So how do you share the files you need to share with your friends? Below, the editor of this site will give you a detailed introduction. I hope it can help you! 1) Open Baidu Cloud APP, first click to select the relevant folder on the homepage, and then click the [...] icon in the upper right corner of the interface; (as shown below) 2) Then click [+] in the "Shared Members" column 】, and finally check all

Do you have the latest activation key for win7 enterprise edition? If you install the official win7 enterprise version, you will be prompted to activate it with the windows7 enterprise product key, otherwise it will not work properly. So the editor will share with you some win7 enterprise version activation passwords, let's take a look. Q3VMJ-TMJ3M-99RF9-CVPJ3-Q7VF3KGMPT-GQ6XF-DM3VM-HW6PR-DX9G8MT39G-9HYXX-J3V3Q-RPXJB-RQ6D79JBBV-7Q7P7-CTDB7-KYBKG-X8HHCP72QK-2Y3B8-YDHDV-29DQB-QKWWM6 JQ

Mango TV has various types of movies, TV series, variety shows and other resources, and users can freely choose to watch them. Mango TV members can not only watch all VIP dramas, but also set the highest definition picture quality to help users watch dramas happily. Below, the editor will bring you some free Mango TV membership accounts for users to use, hurry up and take a look Take a look. Mango TV latest member account free sharing 2023: Note: These are the latest member accounts collected, you can log in directly and use them, do not change the password at will. Account number: 13842025699 Password: qds373 Account number: 15804882888 Password: evr6982 Account number: 13330925667 Password: jgqae Account number: 1703

Title: To solve the problem that Discuz WeChat shares cannot be displayed, specific code examples are needed. With the development of the mobile Internet, WeChat has become an indispensable part of people's daily lives. In website development, in order to improve user experience and expand website exposure, many websites will integrate WeChat sharing functions, allowing users to easily share website content to Moments or WeChat groups. However, sometimes when using open source forum systems such as Discuz, you will encounter the problem that WeChat shares cannot be displayed, which brings certain difficulties to the user experience.
