SoFunction
Updated on 2025-03-02

A brief discussion on the history of Express asynchronous evolution

1. Introduction

In the world of Javascript, asynchronous (asynchronous in JavaScript can block due to single threaded operation of JavaScript) is everywhere.

Express is a very popular web server framework in node environments, and a large proportion of Node Web applications use Express.

When writing server-side code using JavaScript, we inevitably use asynchronously. With the evolution of JavaScript and Node, our asynchronous processing methods have evolved accordingly.

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 obtain notifications of the completion of the asynchronous method. So what are the ways in JavaScript?

2.1. Callback

Callbacks are the most primitive and oldest asynchronous notification mechanism in JS.

function asyncFn(callback) {
 // Use setTimeout to simulate asynchronous setTimeout(function () {
  ('Execution is completed');
  callback(); // Send a notice }, 2000);
}

asyncFn(function () {
 ('I will output after 2s');
});

2.2. Event monitoring

The function to get the result, listen for a certain time. After the asynchronous method is completed, the event is triggered to achieve the effect of notification.

2.3. Publish/Subscribe

Through observer mode, modify the publisher when asynchronously completes. At this time, the publisher will notify the subscriber of the change.

2.4、Promise

Promise is an improvement in the callback function. Using it, we can parallelize asynchronously and avoid callback hell.

function asyncFn() {
 return new Promise((resolve, reject) => {
  // Use setTimeout to simulate asynchronous  setTimeout(function () {
   ('Execution is completed');
   resolve(); // Send a notification (Do you feel the shadow of the callback?)  }, 2000);
 });
}

asyncFn()
 .then(function () {
  ('I will output after 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 use of Generator is relatively complicated. This is another topic and will not be discussed in this article.

function asyncFn() {
 return new Promise((resolve, reject) => {
  // Use setTimeout to simulate asynchronous  setTimeout(function () {
   ('Execution is completed');
   resolve(); // Send a notification (Do you feel the shadow of the callback?)  }, 2000);
 });
}

function* generatorSync() {
 var result = yield asyncFn();
}

var g = generatorSync();
().(()=>{
 ('I will output after 2s');
});

2.6、async...await

It can be said that it is the best solution for handling asynchronous in current JavaScript.

function asyncFn() {
 return new Promise((resolve, reject) => {
  // Use setTimeout to simulate asynchronous  setTimeout(function () {
   ('Execution is completed');
   resolve(); // Send a notification (Do you feel the shadow of the callback?)  }, 2000);
 });
}

async function run(){
 await asyncFn();
 ('I will output after 2s');
}

run();

3. Asynchronous processing in Express

In Express, we generally use solutions: callback function, promise, and async...await.

In order to build a demonstration environment, an express project is initialized through the express-generator. Generally, server-side projects are route calls business logic. So, we also follow this principle:

Open routers/ and we will see the following content. The following demo uses this file to demonstrate.

var express = require('express');
var router = ();

/* GET home page. */
('/', function(req, res, next) {
 ('index', { title: 'Express' });
});

 = router;

3.1. Callback function handles Express asynchronous logic

In Express, routes can load multiple middleware, so we can write business logic according to the middleware writing method. In this way, the asynchronous logic can be split very easily through layers of next.

var express = require('express');
var router = ();

function asyncFn(req, res, next) {
 setTimeout(() => {
   = {}; // Set the currently requested user  next();
 }, 2000);
}

function asyncFn2(req, res, next) {
 setTimeout(() => {
   = {}; // Set user permissions  next();
 }, 2000);
}

function asyncFn3(req, res, next) {
 setTimeout(() => {
   = { title: 'Express Async Test' }; // Set data  ('index'); // Response }, 2000);
}

/* GET home page. */
('/', asyncFn, asyncFn2, asyncFn3); // Execute middleware step by step
 = router;

3.2. Promise handles Express asynchronous logic

In this scheme, multiple business logic is wrapped as functions that return Promise. Combination calls are made through business methods to achieve one-in-one-out effect.

var express = require('express');
var router = ();

function asyncFn(req, res) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
    = {}; // Set the currently requested user   resolve(req);
  }, 2000);
 });
}

function asyncFn2(req) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
    = {}; // Set user permissions   resolve();
  }, 2000);
 });
}

function asyncFn3(res) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
    = { title: 'Express Async Test' }; // Set data   ('index'); // Response  }, 2000);
 });
}

function doBizAsync(req, res, next) {
 asyncFn(req)
  .then(() => asyncFn2(req))
  .then(() => asyncFn3(res))
  .catch(next); // Unified exception handling};

/* GET home page. */
('/', doBizAsync);

 = router;

3.3. async...await handles Express asynchronous logic

In fact, this solution also requires the support of Promise, but the writing method is more intuitive and the error handling is more direct.

It should be noted that Express is an early solution and does not handle global errors on async...await, so it can be used to handle it in a wrapper way.

var express = require('express');
var router = ();

function asyncFn(req) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
    = {}; // Set the currently requested user   resolve(req);
  }, 2000);
 });
}

function asyncFn2(req) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
    = {}; // Set user permissions   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);
  = { title: 'Express Async Test' }; // Set data ('index'); // Response};

const tools = {
 asyncWrap(fn) {
  return (req, res, next) => {
   fn(req, res, next).catch(next); // Async... Error handling of await in Express  }
 }
};

/* GET home page. */
('/', (doBizAsync)); // You need to wrap it with tools
 = router;

4. Summary

Although koa supports newer and better usage (koa is generator, koa2 native async). But as I have been following me since node, I still have a special affection for Express.

Some of the above solutions are no different from those used in koa. Combined with Express's huge ecosystem, it is like adding wings to the tiger.

This articleGithub address

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.