Maison  >  Article  >  interface Web  >  Comparez les différences et les connexions entre les modèles de middleware express et koa

Comparez les différences et les connexions entre les modèles de middleware express et koa

巴扎黑
巴扎黑original
2017-08-11 10:08:572620parcourir

Cet article présente principalement la comparaison détaillée entre les modes middleware express et koa. L'éditeur pense que c'est assez bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur et jetons un coup d'œil.

Cause

J'ai récemment appris à utiliser koa Puisque koa est un framework web assez basique, un complet. L'application Web est La plupart des éléments requis sont introduits sous la forme d'un middleware, tel que koa-router, koa-view, etc. C'est mentionné dans la documentation de koa : le modèle middleware de koa est différent de celui d'express. koa est en forme d'oignon, tandis qu'express est linéaire. Quant à la raison pour laquelle c'est le cas, de nombreux articles sur Internet ne fournissent pas d'analyse détaillée. Ou tout simplement, ce sont les caractéristiques de async/wait. Ne parlons pas de savoir si cette affirmation est vraie ou fausse. Pour moi, cette affirmation est encore trop vague. J'ai donc décidé d'analyser les similitudes et les différences dans les principes et l'utilisation des deux implémentations middleware à travers le code source.

Par souci de simplicité, express est remplacé ici par connect (le principe de mise en œuvre est le même)

Utilisation

Les deux sont documentés dans le site officiel (github) Sous réserve de

connexion

Ce qui suit est l'utilisation du site officiel :


var connect = require('connect');
var http = require('http');

var app = connect();

// gzip/deflate outgoing responses
var compression = require('compression');
app.use(compression());

// store session state in browser cookie
var cookieSession = require('cookie-session');
app.use(cookieSession({
 keys: ['secret1', 'secret2']
}));

// parse urlencoded request bodies into req.body
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));

// respond to all requests
app.use(function(req, res){
 res.end('Hello from Connect!\n');
});

//create node.js http server and listen on port
http.createServer(app).listen(3000);

D'après le document que l'on peut voir Oui, connect fournit une fonction de routage simple :


app.use('/foo', function fooMiddleware(req, res, next) {
 // req.url starts with "/foo"
 next();
});
app.use('/bar', function barMiddleware(req, res, next) {
 // req.url starts with "/bar"
 next();
});

Le middleware de connect est linéaire. Après ensuite, continuez vers. Recherchez le prochain middleware.Ce mode est intuitif.Il est également facile de comprendre ci-dessus que le middleware est une série de tableaux et que la méthode de traitement pour trouver les itinéraires correspondants est également un middleware. En fait, connect est également implémenté de cette manière.

app.use consiste à insérer un nouveau middleware dans le tableau middleware. L'exécution du middleware repose sur la méthode privée app.handle pour le traitement, et il en va de même pour express.

koa

Par rapport à connect, le modèle middleware de koa n'est pas si intuitif Empruntons la représentation graphique à Internet :

<.>

Autrement dit, koa reviendra après avoir traité le middleware, ce qui nous donne plus de marge de manœuvre. Jetons un coup d'œil à l'exemple du site officiel de koa :


<.>

Évidemment, lorsque le middleware de traitement koa rencontre wait next(), il mettra en pause le middleware actuel et traitera le prochain middleware, et enfin reviendra pour continuer le traitement des tâches restantes, même si c'est très compliqué à dire. , mais intuitivement nous avons un sentiment vaguement familier : n'est-ce pas juste une fonction de rappel ? Ne parlons pas ici de la méthode d'implémentation spécifique, mais il s'agit bien d'une fonction de rappel. Cela n'a rien à voir avec les fonctionnalités d'async/await.
const Koa = require(&#39;koa&#39;);
const app = new Koa();

// x-response-time

app.use(async (ctx, next) => {
 const start = Date.now();
 await next();
 const ms = Date.now() - start;
 ctx.set(&#39;X-Response-Time&#39;, `${ms}ms`);
});

// logger

app.use(async (ctx, next) => {
 const start = Date.now();
 await next();
 const ms = Date.now() - start;
 console.log(`${ctx.method} ${ctx.url} - ${ms}`);
});

// response

app.use(async ctx => {
 ctx.body = &#39;Hello World&#39;;
});

app.listen(3000);

Brève analyse du code source

La principale différence entre le mode middleware connect et koa réside dans l'implémentation de next Examinons brièvement l'implémentation de next entre les deux. .

connect

Le code source de connect est assez petit et ne contient qu'environ 200 lignes avec des commentaires. Il semble très clair que le traitement du middleware de connexion réside dans le proto de la méthode privée. .handle. , de la même manière, next est également implémenté ici


Après avoir supprimé le code obscurci, nous pouvons voir que l'implémentation suivante est également très simple. Une séquence d'appels récursifs à la recherche de middleware. Continuez à appeler ensuite. Le code est assez simple mais l'idée mérite d'être apprise.
// 中间件索引
var index = 0
function next(err) {


 // 递增
 var layer = stack[index++];

 // 交由其他部分处理
 if (!layer) {
  defer(done, err);
  return;
 }

 // route data
 var path = parseUrl(req).pathname || &#39;/&#39;;
 var route = layer.route;

 // 递归
 // skip this layer if the route doesn&#39;t match
 if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) {
  return next(err);
 }

 // call the layer handle
 call(layer.handle, route, err, req, res, next);
 }

Où est la méthode de traitement tierce. D'autres parties traitant des sous-applications et du routage ont été supprimées. Ce n'est pas la question

koa

koa sépare l'implémentation de next dans un package séparé. Le code est plus simple, mais il implémente une fonction apparemment plus complexe

<.>


En regardant le code traité ci-dessus, certains étudiants peuvent encore être confus.

function compose (middleware) {
 return function (context, next) {
 // last called middleware #
 let index = -1
 return dispatch(0)
 function dispatch (i) {
  index = i
  try {
  return Promise.resolve(fn(context, function next () {
   return dispatch(i + 1)
  }))
  } catch (err) {
  return Promise.reject(err)
  }
 }
 }
}
Ensuite, continuons le traitement :


De cette façon, le programme est plus simple et n'a rien à voir avec async/await. Voyons le résultat. bon

function compose (middleware) {

 return function (context, next) {
 // last called middleware #
 let index = -1
 return dispatch(0)
 function dispatch (i) {
  index = i
  let fn = middleware[i]
  if (i === middleware.length) {
  fn = next
  }
  if (!fn) return
  return fn(context, function next () {
  return dispatch(i + 1)
  })
 }
 }
}


En exécutant le programme ci-dessus, nous pouvons trouver la sortie dans l'ordre :

var ms = [
 function foo (ctx, next) {
 console.log(&#39;foo1&#39;)
 next()
 console.log(&#39;foo2&#39;)
 },
 function bar (ctx, next) {
 console.log(&#39;bar1&#39;)
 next()
 console.log(&#39;bar2&#39;)
 },
 function qux (ctx, next) {
 console.log(&#39;qux1&#39;)
 next()
 console.log(&#39;qux2&#39;)
 }
]

compose(ms)()
foo1

bar1

qux1

qux2
bar2
foo2


est également ce qu'on appelle le modèle d'oignon de koa. À ce stade, nous pouvons tirer la conclusion que le modèle middleware de koa n'a aucun lien réel avec async ou Generator , mais. koa met l'accent sur la priorité asynchrone. La pause dite du middleware est uniquement due à la fonction de rappel (à mon avis, il n'y a aucune différence entre promise.then et callback, et même async/await est également une forme de rappel).

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