Le middleware Node fait principalement référence à la méthode d'encapsulation du traitement détaillé des requêtes http. Son essence est de laisser des filtres spécifiques le traiter avant d'entrer dans un traitement métier spécifique, l'introduction du middleware Node peut simplifier et encapsuler certains traitements logiques de base ; détails.
L'environnement d'exploitation de ce tutoriel : système Windows 10, version node v12.21.0, ordinateur Dell G3.
Qu'est-ce que le middleware de nœud ?
Une explication approfondie des principes du middleware nodejs
Avant-propos
Le middleware est un type de logiciel entre les systèmes d'application et le logiciel système. Il utilise les services de base (fonctions) fournis par le logiciel système pour connecter le réseau. Chaque partie du système d'application ou différentes applications peuvent atteindre l'objectif de partage de ressources et de partage de fonctions.
Dans NodeJS, middleware fait principalement référence à la méthode d'encapsulation des détails de la demande http. Nous savons tous que les requêtes http impliquent souvent de nombreuses actions, comme suit : Filtrage IP Livraison de la chaîne de requête Analyse du corps de la requête Traitement des informations sur les cookies Vérification des autorisations Journalisation Middleware de gestion de session (session) Middleware de compression gzip (comme compresser) * Gestion des erreurs
Bien sûr, il existe de nombreuses actions de traitement personnalisées Pour les applications Web, nous ne voulons pas comprendre chaque travail de traitement détaillé, mais espérons pouvoir nous concentrer sur le développement commercial pour y parvenir. dans le but d'améliorer l'efficacité du développement, le Middleware de nœud est introduit pour simplifier et encapsuler ces détails de traitement logique de base. Le
middleware de nœud est essentiellement avant d'entrer dans un traitement métier spécifique, laissez le filtre spécifique le gérer en premier. Comme le montre la figure ci-dessous :
Les frameworks nodejs grand public que nous voyons actuellement, tels que connect, koa, express, egg, nest, etc., sont tous indissociable du middleware.Le concept de conception, donc afin de donner à chacun un aperçu plus approfondi du monde de nodejs, nous avons étudié de manière comparative les principes de mise en œuvre du middleware
Après avoir compris le concept de middleware de nœud, nous implémenterons manuellement le. middleware , Enfin, nous analyserons brièvement les idées d'implémentation du middleware dans koa Le plan de l'article est le suivant : Implémentation des principes de base du middleware de noeud Méthode d'implémentation de la clé intermédiaire koa* Utilisez le mécanisme du middleware koa pour implémenter votre propre koa. middleware
D'après l'introduction ci-dessus, nous pouvons voir que le middleware est la logique de traitement du début de la requête http à la fin de la réponse. Il doit généralement traiter la demande et la réponse. Le problème que nous devons prendre en compte lors de la mise en œuvre du mode middleware de nœud est qu'en ce qui concerne la coexistence de plusieurs middlewares, nous devons réfléchir à la manière d'automatiser l'exécution de plusieurs middlewares, sinon seul le premier middleware sera exécuté dans le processus de la demande à la réponse. notre forme de middleware de base est donc la suivante :
const middleware = (req, res, next) => { // 请求处理逻辑 next()}
Ensuite, écrivons un cas simple pour voir comment le middleware est implémenté.
// 定义几个中间间函数const m1 = (req, res, next) => { console.log('m1 run') next()}const m2 = (req, res, next) => { console.log('m2 run') next()}const m3 = (req, res, next) => { console.log('m3 run') next()}// 中间件集合const middlewares = [m1, m2, m3]function useApp (req, res) { const next = () => { // 获取第一个中间件 const middleware = middlewares.shift() if (middleware) { middleware(req, res, next) } } next()}// 第一次请求流进入useApp()
À partir du code ci-dessus, il ne nous est pas difficile de découvrir le rôle de next, qui est la clé pour appeler automatiquement les paramètres de la chaîne middleware. Le résultat d'impression est le suivant :
m1 runm2 runm3 run
Ce qui précède implémente le mode d'exécution de base du middleware, mais nous devons également prendre en compte les problèmes asynchrones, si le middleware s'appuie également. sur les modules tiers ou le support API, tels que le service de vérification, d'identification, etc., nous devons exécuter next dans le rappel du middleware asynchrone pour garantir la séquence d'exécution normale des appels, comme indiqué dans le code suivant :
const m2 = (req, res, next) => { fetch('/xxxxx').then(res => { next() })}
Il existe également un scénario middleware, tel que le middleware de journalisation, le middleware de surveillance des demandes, ils exécuteront la logique pertinente avant et après le traitement métier. À ce stade, nous devons être en mesure d'effectuer un traitement secondaire sur la fonction next. empaquetez la valeur de retour de next dans promise, afin qu'elle puisse être utilisée pendant le traitement métier. Une fois terminé, continuez le traitement de la logique middleware via le rappel then Comme indiqué ci-dessous :
function useApp (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // 将返回值包装为Promise对象 return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("end") } } next()}
À ce stade, nous. peut l'appeler de la manière suivante :
const m1 = (req, res, next) => { console.log('m1 start') return next().then(() => { console.log('m1 end') })}
Ci-dessus, nous avons implémenté un modèle de conception de middleware de base, bien sûr nous pouvons également utiliser async et attendre pour l'implémenter, la méthode d'écriture sera plus élégante et simple. exemple de l'auteur :
const m1 = async (req, res, next) => { // something... let result = await next(); } const m2 = async (req, res, next) => { // something... let result = await next(); } const m3 = async (req, res, next) => { // something... let result = await next(); return result; }const middlewares = [m1, m2, m3];function useApp (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("end") } } next() }// 启动中间件useApp()
在koa2框架中, 中间件的实现方式也是将next()方法返回值封装为Promise对象,实现了其提出的洋葱圈模型,如下图所示:
koa2框架的中间件实现原理很优雅,笔者觉得很必要研究一下, 这里展示一下其核心思路:
function compose (middleware) { // 提前判断中间件类型,防止后续错误 if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!') for (const fn of middleware) { // 中间件必须为函数类型 if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!') } return function (context, next) { // 采用闭包将索引缓存,来实现调用计数 let index = -1 return dispatch(0) function dispatch (i) { // 防止next()方法重复调用 if (i
学习了中间件的设计机制和原理, 我们是不是想马上写一个中间件呢? 笔者这里给大家举一个例子. 在H5-Dooring项目的服务端代码中, 我们需要对用户登录权限进行分发, 此时我们提供统一个中间件来处理, 如下代码所示:
// 模拟数据库操作const token = db.user();// router或者koa的中间件一定要用await处理next,否则将不能正常响应数据export default async (ctx, next) => { const t = ctx.request.header.authorization let uid = ctx.request.header['x-requested-with'] let uidArr = uid.split(',') if(uidArr.length > 1) { uid = uidArr.pop().trim() } if(token[uid] && token[uid][1] === t) { await next() }else { ctx.status = 403; ctx.body = { state: 403, msg: '你没有权限操作' } } }
以上代码即实现用户登录态处理, 如果用户在没有登录的情况下防问任何需要登录的接口, 都将返回权限不足或则在请求库中让其重定向到登录页面.
推荐学习:《node.js视频教程》
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!