Maison >interface Web >js tutoriel >Maîtriser Express.js : une plongée approfondie

Maîtriser Express.js : une plongée approfondie

Susan Sarandon
Susan Sarandonoriginal
2025-01-05 06:46:40371parcourir

Mastering Express.js: A Deep Dive

Express est un framework d'application de serveur Web extrêmement couramment utilisé dans Node.js. Essentiellement, un framework est une structure de code qui adhère à des règles spécifiques et présente deux caractéristiques clés :

  • Il encapsule les API, permettant aux développeurs de se concentrer davantage sur l'écriture du code métier.
  • Il a établi des processus et des spécifications standards.

Les principales fonctionnalités du framework Express sont les suivantes :

  • Il peut configurer un middleware pour répondre à diverses requêtes HTTP.
  • Il définit une table de routage pour exécuter différents types d'actions de requête HTTP.
  • Il prend en charge la transmission de paramètres aux modèles pour obtenir un rendu dynamique des pages HTML.

Cet article analysera comment Express implémente l'enregistrement du middleware, le prochain mécanisme et la gestion des routes en implémentant une simple classe LikeExpress.

Analyse expresse

Explorons d'abord les fonctions qu'il propose à travers deux exemples de code Express :

Exemple de site Web officiel Express Hello World

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`);
});

Analyse du fichier d'entrée app.js

Ce qui suit est le code du fichier d'entrée app.js du projet Express généré par l'échafaudage du générateur express :

// Handle errors caused by unmatched routes
const createError = require('http-errors');
const express = require('express');
const path = require('path');

const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');

// `app` is an Express instance
const app = express();

// View engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// Parse JSON format data in post requests and add the `body` field to the `req` object
app.use(express.json());
// Parse the urlencoded format data in post requests and add the `body` field to the `req` object
app.use(express.urlencoded({ extended: false }));

// Static file handling
app.use(express.static(path.join(__dirname, 'public')));

// Register top-level routes
app.use('/', indexRouter);
app.use('/users', usersRouter);

// Catch 404 errors and forward them to the error handler
app.use((req, res, next) => {
    next(createError(404));
});

// Error handling
app.use((err, req, res, next) => {
    // Set local variables to display error messages in the development environment
    res.locals.message = err.message;
    // Decide whether to display the full error according to the environment variable. Display in development, hide in production.
    res.locals.error = req.app.get('env') === 'development'? err : {};
    // Render the error page
    res.status(err.status || 500);
    res.render('error');
});

module.exports = app;

À partir des deux segments de code ci-dessus, nous pouvons voir que l'application d'instance Express comporte principalement trois méthodes principales :

  1. app.use([path,] callback [, callback...]) : utilisé pour enregistrer le middleware. Lorsque le chemin de la requête correspond aux règles définies, la fonction middleware correspondante sera exécutée.
    • path : Spécifie le chemin d’appel de la fonction middleware.
    • callback : La fonction de rappel peut prendre diverses formes. Il peut s'agir d'une seule fonction middleware, d'une série de fonctions middleware séparées par des virgules, d'un tableau de fonctions middleware ou d'une combinaison de tout ce qui précède.
  2. app.get() et app.post() : ces méthodes sont similaires à use(), également pour l'enregistrement du middleware. Cependant, ils sont liés aux méthodes de requête HTTP. Ce n'est que lorsque la méthode de requête HTTP correspondante est utilisée que l'enregistrement du middleware concerné sera déclenché.
  3. app.listen() : responsable de la création d'un serveur http et de la transmission des paramètres requis par server.listen().

Implémentation du code

Sur la base de l'analyse des fonctions du code Express, nous savons que la mise en œuvre d'Express se concentre sur trois points :

  • Le processus d'enregistrement des fonctions middleware.
  • Le mécanisme suivant de base dans les fonctions middleware.
  • Gestion des itinéraires, en mettant l'accent sur la correspondance des chemins.

Sur la base de ces points, nous implémenterons ci-dessous une simple classe LikeExpress.

1. Structure de base de la classe

Tout d'abord, clarifiez les principales méthodes que cette classe doit implémenter :

  • use() : implémente l'enregistrement général du middleware.
  • get() et post() : implémentez l'enregistrement du middleware lié aux requêtes HTTP.
  • Listen() : Il s’agit essentiellement de la fonction Listen() de httpServer. Dans la fonction Listen() de cette classe, un httpServer est créé, les paramètres sont transmis, les requêtes sont écoutées et la fonction de rappel (req, res) => {} est exécuté.

Revoir l'utilisation du serveur http natif de Node :

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`);
});

En conséquence, la structure de base de la classe LikeExpress est la suivante :

// Handle errors caused by unmatched routes
const createError = require('http-errors');
const express = require('express');
const path = require('path');

const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');

// `app` is an Express instance
const app = express();

// View engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// Parse JSON format data in post requests and add the `body` field to the `req` object
app.use(express.json());
// Parse the urlencoded format data in post requests and add the `body` field to the `req` object
app.use(express.urlencoded({ extended: false }));

// Static file handling
app.use(express.static(path.join(__dirname, 'public')));

// Register top-level routes
app.use('/', indexRouter);
app.use('/users', usersRouter);

// Catch 404 errors and forward them to the error handler
app.use((req, res, next) => {
    next(createError(404));
});

// Error handling
app.use((err, req, res, next) => {
    // Set local variables to display error messages in the development environment
    res.locals.message = err.message;
    // Decide whether to display the full error according to the environment variable. Display in development, hide in production.
    res.locals.error = req.app.get('env') === 'development'? err : {};
    // Render the error page
    res.status(err.status || 500);
    res.render('error');
});

module.exports = app;

2. Enregistrement du middleware

De app.use([path,] callback [, callback...]), nous pouvons voir que le middleware peut être un tableau de fonctions ou une seule fonction. Pour simplifier la mise en œuvre, nous traitons uniformément le middleware comme un ensemble de fonctions. Dans la classe LikeExpress, les trois méthodes use(), get() et post() peuvent toutes implémenter l'enregistrement du middleware. Seul le middleware déclenché varie en raison des différentes méthodes de requête. Nous considérons donc :

  • Résumé d'une fonction générale d'enregistrement du middleware.
  • Création de tableaux de fonctions middleware pour ces trois méthodes afin de stocker le middleware correspondant aux différentes requêtes. Puisque use() est une méthode générale d'enregistrement de middleware pour toutes les requêtes, le tableau stockant le middleware use() est l'union des tableaux pour get() et post().

Tableau de files d'attente middleware

Le tableau middleware doit être placé dans une zone publique pour un accès facile par les méthodes de la classe. Nous mettons donc le tableau middleware dans la fonction constructeur constructor().

const http = require("http");
const server = http.createServer((req, res) => {
    res.end("hello");
});
server.listen(3003, "127.0.0.1", () => {
    console.log("node service started successfully");
});

Fonction d'enregistrement du middleware

L'enregistrement du middleware signifie stocker le middleware dans le tableau de middleware correspondant. La fonction d'enregistrement du middleware doit analyser les paramètres entrants. Le premier paramètre peut être une route ou un middleware, il faut donc d'abord déterminer s'il s'agit d'une route. Si tel est le cas, affichez-le tel quel ; sinon, la valeur par défaut est la route racine, puis convertissez les paramètres middleware restants en un tableau.

const http = require('http');

class LikeExpress {
    constructor() {}

    use() {}

    get() {}

    post() {}

    // httpServer callback function
    callback() {
        return (req, res) => {
            res.json = function (data) {
                res.setHeader('content-type', 'application/json');
                res.end(JSON.stringify(data));
            };
        };
    }

    listen(...args) {
        const server = http.createServer(this.callback());
        server.listen(...args);
    }
}

module.exports = () => {
    return new LikeExpress();
};

Implémentation de use(), get() et post()

Avec la fonction générale d'enregistrement du middleware register(), il est facile d'implémenter use(), get() et post(), il suffit de stocker le middleware dans les tableaux correspondants.

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`);
});

3. Traitement de correspondance d'itinéraire

Lorsque le premier paramètre de la fonction d'enregistrement est une route, la fonction middleware correspondante ne sera déclenchée que lorsque le chemin de la requête correspond à la route ou est sa sous-route. Nous avons donc besoin d'une fonction de correspondance de route pour extraire le tableau middleware de la route correspondante en fonction de la méthode de requête et du chemin de requête pour que la fonction callback() suivante s'exécute :

// Handle errors caused by unmatched routes
const createError = require('http-errors');
const express = require('express');
const path = require('path');

const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');

// `app` is an Express instance
const app = express();

// View engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// Parse JSON format data in post requests and add the `body` field to the `req` object
app.use(express.json());
// Parse the urlencoded format data in post requests and add the `body` field to the `req` object
app.use(express.urlencoded({ extended: false }));

// Static file handling
app.use(express.static(path.join(__dirname, 'public')));

// Register top-level routes
app.use('/', indexRouter);
app.use('/users', usersRouter);

// Catch 404 errors and forward them to the error handler
app.use((req, res, next) => {
    next(createError(404));
});

// Error handling
app.use((err, req, res, next) => {
    // Set local variables to display error messages in the development environment
    res.locals.message = err.message;
    // Decide whether to display the full error according to the environment variable. Display in development, hide in production.
    res.locals.error = req.app.get('env') === 'development'? err : {};
    // Render the error page
    res.status(err.status || 500);
    res.render('error');
});

module.exports = app;

Ensuite, dans la fonction de rappel callback() du httpServer, extrayez le middleware qui doit être exécuté :

const http = require("http");
const server = http.createServer((req, res) => {
    res.end("hello");
});
server.listen(3003, "127.0.0.1", () => {
    console.log("node service started successfully");
});

4. Mise en œuvre du prochain mécanisme

Les paramètres de la fonction middleware Express sont req, res et next, où next est une fonction. Ce n'est qu'en l'appelant que les fonctions middleware peuvent être exécutées dans l'ordre, similaire à next() dans ES6 Generator. Dans notre implémentation, nous devons écrire une fonction next() avec les exigences suivantes :

  • Extrayez un middleware du tableau de file d'attente des middlewares dans l'ordre à chaque fois.
  • Passez la fonction next() dans le middleware extrait. Étant donné que le tableau middleware est public, chaque fois que next() est exécuté, la première fonction middleware du tableau sera supprimée et exécutée, obtenant ainsi l'effet d'une exécution séquentielle du middleware.
const http = require('http');

class LikeExpress {
    constructor() {}

    use() {}

    get() {}

    post() {}

    // httpServer callback function
    callback() {
        return (req, res) => {
            res.json = function (data) {
                res.setHeader('content-type', 'application/json');
                res.end(JSON.stringify(data));
            };
        };
    }

    listen(...args) {
        const server = http.createServer(this.callback());
        server.listen(...args);
    }
}

module.exports = () => {
    return new LikeExpress();
};

Code express

constructor() {
    // List of stored middleware
    this.routes = {
        all: [], // General middleware
        get: [], // Middleware for get requests
        post: [], // Middleware for post requests
    };
}

Leapcell : la plate-forme sans serveur de nouvelle génération pour l'hébergement Web, les tâches asynchrones et Redis

Mastering Express.js: A Deep Dive

Enfin, permettez-moi de vous présenter une plateforme très adaptée au déploiement d'Express : Leapcell.

Leapcell est une plateforme sans serveur présentant les caractéristiques suivantes :

1. Prise en charge multilingue

  • Développer avec JavaScript, Python, Go ou Rust.

2. Déployez gratuitement un nombre illimité de projets

  • Payez uniquement pour l'utilisation – pas de demandes, pas de frais.

3. Rentabilité imbattable

  • Payez à l'utilisation sans frais d'inactivité.
  • Exemple : 25 $ prend en charge 6,94 millions de requêtes avec un temps de réponse moyen de 60 ms.

4. Expérience de développeur rationalisée

  • Interface utilisateur intuitive pour une configuration sans effort.
  • Pipelines CI/CD entièrement automatisés et intégration GitOps.
  • Mesures et journalisation en temps réel pour des informations exploitables.

5. Évolutivité sans effort et hautes performances

  • Mise à l'échelle automatique pour gérer facilement une concurrence élevée.
  • Zéro frais opérationnels – concentrez-vous uniquement sur la construction.

Explorez-en davantage dans la documentation !

Twitter de Leapcell : https://x.com/LeapcellHQ

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn