当前位置:网站首页>KOA Quick Start

KOA Quick Start

2022-06-29 02:08:00 Cheyenne.

Koa Démarrage rapide

Koa - Oui. Express La classe originale de développeurs utilise ES2015 Nouvelles propriétés dans(Surtout Generator )Réinventer le nouveau Web Cadre——Koa,Koa L'intention initiale était de résoudre complètement le problème dansNode WebProblèmes asynchrones dans le développement,In ES2015 Pas encore. Node Quand il est entièrement supporté,Exécution Koa Le projet doit être lancé Node Ajouter--harmonyParamètres.

Koa La philosophie et Connect Plus similaire,Aucun intergiciel n'est disponible à l'interne,Express Les fichiers statiques et les itinéraires conservés dans sont également supprimés, Un échafaudage qui n'est qu'un appel à un intergiciel .

Koa De développement Koa1.x Et Koa2 Deux étapes,La différence entre les deux est que Koa2 Utilisé ES2017 Moyenne async Méthode de traitement des appels d'intergiciels (Koa1.x Utilisé generator), L'attribut est déjà dans v7.6.0 Après Node Le support natif est disponible dans la version .

1. Koa1.x Avec Koa2

Déjà mentionné,Koa1.x Et Koa2 La principale différence est que le premier utilise Generator,Ce dernier utilise async Méthodes de gestion des intergiciels .

In Web En cours de développement,Bien que Node Asynchrone en soi , Mais nous voulons toujours pouvoir effectuer certaines opérations dans l'ordre , Et la mise en œuvre du Code doit être aussi simple que possible . Par exemple, HTTP Sur demande, Nous voulons d'abord enregistrer les informations demandées , Puis les opérations liées à la base de données , Retour au résultat correspondant .

Dans le développement réel, Ces opérations sont abstraites en intergiciels , Les appels sont généralement asynchrones , Notre question est de savoir comment contrôler l'ordre des appels dans l'intergiciel .

In Koa1.x Dans la version de,Et donc utilisé ES2015 Dans la proposition Generator Fonction comme principal moyen de traitement asynchrone .

Il y en a un en bas. Koal1x Exemples.

const Koa = require('Koa');
const app = Koa();

app.use(function *(next) {
    
  const start = new Date();
  // Appeler le prochain intergiciel, Réponse immédiate  'Hello world'
  yield next;
  const ms = new Date() - start;
  //  Impression du temps écoulé entre la demande et la réponse 
  console.log('%s %s - %s', this.method, this.url, ms);
});

app.use(function *() {
    
  this.body = 'Hello world';
});

app.listen(3000);

Lorsque l'utilisateur accède localhost:3000 Heure,Imprimez d'abord hello world ,Réexportationlog Information.

Koa1.x Le traitement des intergiciels est basé sur co Module,ES2017 A été ajouté au projet async Fonctions,Koa Publié pour 2.0 Version, Cette version est abandonnée Genrator Fonctions et co Module,Entièrement utilisé async Fonction à mettre en œuvre,async Fonction dans Node v7.6.0 Ce n'est qu'après que le soutien complet a été obtenu ,Donc, utilisez Koa2 Développement,Local Node L'environnement est de préférence supérieur à 7.6.0.

En plus de ça,,Koa Et Express La plus grande différence est que Koa Les différents intergiciels ont été dépouillés , L'avantage de cette approche est qu'elle peut rendre le cadre plus léger ,L'inconvénient est Koa Le temps de développement est relativement court , La qualité des différents intergiciels est inégale ,1.x Et 2.x Il y a aussi des problèmes de compatibilité avec l'intergiciel de , Mais pour la plupart des intergiciels couramment utilisés , C'est déjà fait. Koa2.0 Appui.

In Koa Projet GitHub Page d'accueil https:/github.com/Koajs Moyenne,Listé Koa Le projet lui - même et la liste officielle des intergiciels ,Les développeurs peuvent égalementGitHub Recherche moyenne, Trouver des intergiciels plus actifs .

Dans cet article,Nous présentons principalement Koa2 Utilisation de, Comme mentionné plus loin Koa Représentation Koa2.0.

2. context Objet

Tout d'abord,, Nous regardons l'exemple le plus simple pour commencer Koa Utilisation de.

const Koa = require('Koa');
const app = Koa();

app.use(ctx => {
    
  ctx.body = 'Hello World';
});

app.listen(3000);

Node Offre request(IncomingMessage)Et response(ServerReponse)Deux objets,Koa Encapsule les deux dans le même objet ,C'est - à - dire: context,Abréviations: ctx.

context De nombreuses méthodes et propriétés sont encapsulées dans ,Principalement à partir de request Etresponse Obtenu par délégation dans l'objet ,Voici la Liste ctx Quelques propriétés de l'encapsulation de l'objet et leur origine :

  1. From request
  • ctx.header
  • ctx.headers
  • ctx.method
  • ctx.url
  • ctx.originalUrl
  • ctx.origin
  • ctx.href
  • ctx.path
  • ctx.query
  • ctx.querystring
  • ctx.host
  • ctx.hostname
  • ctx.fresh
  • ctx.stale
  • ctx.socket
  • ctx.protocol
  • ctx.secure
  • ctx.ip
  • ctx.ips
  • ctx.subdomains
  • ctx.is()
  • ctx.accepts()
  • ctx.acceptsEncodings()
  • ctx.acceptsCharsets()
  • ctx.acceptsLanguages()
  • ctx.get()
  1. From response
  • ctx.body
  • ctx.status
  • ctx.message
  • ctx.length
  • ctx.type
  • ctx.headerSent
  • ctx.redirect()
  • ctx.attachment()
  • ctx.set()
  • ctx.append()
  • ctx.remove()
  • ctx.lastModified
  • ctx.etag

En plus des propriétés auto - encapsulées ,ctx Permet également un accès direct aux objets natifs ,ctx.req Et ctx.res C'est - à - dire qu'il représente l'original. request Et response Objet,Par exemple ctx.req.url Et ctx.url C'est le même objet..

En plus des propriétés énumérées ci - dessus ,ctx Les objets s'encapsulent eux - mêmes ,Par exemple ctx.request Et ctx.response , La différence entre eux et les objets natifs est qu'il n'y a qu'une partie des attributs communs à l'intérieur , On pourrait essayer de relier les objets natifs à ctx Les objets encapsulés sont imprimés séparément pour comparaison :

const Koa = require('Koa');
const app = Koa();

app.use(ctx => {
    
  console.log(ctx.request);
  console.log(ctx.response);
});

app.listen(3000);

Accès à localhost:3000,Comme vous pouvez le voir,, La structure des deux est très différente de celle de l'objet natif ,ctx.response Seulement quelques propriétés de base , Aucun événement ou méthode n'est enregistré ci - dessus , Cela signifie que la méthode d'utilisation suivante est incorrecte :

fs.createReadStream('foo.txt').pipe(ctx.response);

Le code ci - dessus va lancer TypeError:dest.on is not a function Erreur,La raison en est simple.,ctx.response Juste un objet simple , Aucun événement défini ,À utiliser pipe Méthodes, Code à modifier :

fs.createReadStream('foo.txt').pipe(ctx.res);
  1. ctx.state

state La propriété est un espace de noms officiellement recommandé , Si un développeur veut passer un message de l'arrière - plan à l'avant - plan , Les propriétés peuvent être suspendues à ctx.state En bas,Ceci et react Les concepts de , .Par exemple, nous cherchons un utilisateur dans la base de données id

ctx.state.user = await User.find(id);
  1. D'autres méthodes d'attributs
ctx.app // ctx C'est exact. app Référence de l'objet
ctx.cookies.get(name, [options]) // Accès cookie
ctx.cookies.set(name, value, [options]) // Paramètres cookie
ctx.throw([msg], [status], [properties]) //  La méthode utilisée pour lancer l'exception 
// Par exemple
// ctx.throw('name required', 400);
// Ce code correspond à:
// const err = new Error('name required');
// err.status = 400;
// err.expose = true;
// throw err;
  1. Traitement http Demande

Ce qui précède mentionne également ,Koa In ctx Encapsulé dans l'objet request Et response Objet, Alors, on s'en occupe. http Sur demande,Utiliser ctx Pour que tout soit fait .

Dans le code ci - dessus,Nous utilisons:

ctx.body = "Hello World";

équivalent à:

res.statusCode = 200;
res.end("Hello World");

ctx équivalent à ctx.request Ou ctx.response Alias de,Jugement http Le type de demande peut être obtenu par ctx.method Pour juger,get Les paramètres demandés peuvent être obtenus par ctx.query Accès.

Par exemple,Lorsque l'utilisateur accède localhost:3000?kindName=Node Heure, Le routage suivant peut être défini .

app.get('/', async (ctx, next) => {
    
  console.log(ctx.method); // GET
  console.log(ctx.query); // { kindName: 'Node' }
  // TODO
  await next();
});

Koa Traitement get Demande simple,Directement à travers ctx.req.<param> Je peux l'avoir. get Valeur du paramètre,post Le traitement des demandes est un peu plus compliqué ,Généralement utilisé bodyParser Cet intergiciel est utilisé pour le traitement , Mais aussi pour les formulaires ordinaires , Obtenir le format ctx.request.body.<param> .

Par exemple, nous construisons un simple fom Utilisé pour saisir le nom d'utilisateur et le mot de passe :

<form action="/login" method="post">
  <input name="name">
  <input name="password" type="password">
  <input type="submit" value="Submit">
</form>

Le Code de routage correspondant du côté serveur peut être écrit comme :

router.post('/login', (ctx, next) => {
    
  const name = ctx.request.body.name;
  const password = ctx.request.body.password;
});

3. middleware

3.1 Le concept de middleware

En introduction Koa Avant l'intergiciel, Pour l'instant, regardons d'abord Express ,Parce queKoa La plupart des idées de conception des intergiciels proviennent de Connect,Et Express Encore une fois, Connect Une extension.

Express Il est lui - même composé d'un routage et d'un intergiciel ,Essentiellement,,Express L'opération est d'appeler les différents intergiciels .

Un intergiciel est essentiellement une fonction qui reçoit une demande et agit en conséquence , Cette fonction reçoit habituellement req Et res Comme paramètre,Pour que request Et response Objet à utiliser,In Web En application, Chaque demande du client , Il faut d'abord passer par le traitement de l'intergiciel pour continuer à descendre .

Le troisième paramètre du Middleware est généralement écrit next, Il représente une méthode , Le prochain intergiciel . Si on appelle dans le corps de la méthode de l'intergiciel next Méthodes, Cela signifie que la demande sera traitée par le prochain intergiciel .

Par exemple, les fonctions suivantes peuvent être utilisées pour faire un intergiciel .

function md(req, res, next) {
    
  console.log("I am a Middleware");
  next();
}

3.2 Fonction de l'intergiciel

Parce que l'intergiciel est toujours une fonction , Alors il peut le faire. Node Tout ce que le Code peut faire , En outre, des modifications ont été apportées request Et response Objet、Demande de clôture-Cycle de réponse, Et invoquer des fonctions telles que le prochain intergiciel , Cela se fait généralement par des appels internes next Comment le faire. S'il n'y a pas d'appel dans un intergiciel next Méthodes, Cela signifie que le traitement de la demande est terminé , Le prochain intergiciel ne sera pas exécuté .

3.3 Chargement des intergiciels

Utilisation du chargement des intergiciels use Comment réaliser,Cette méthode est définie à Express Ou Koa Sur l'Instance de l'objet, Par exemple, charger l'intergiciel défini ci - dessus md

const app = express();
app.use(md);

3.4 Express Middleware in

Express Les applications peuvent utiliser les intergiciels suivants:

  • Intergiciels au niveau de l'application
  • Middleware de niveau routage
  • Middleware de gestion des erreurs
  • Intergiciel intégré
  • Intergiciels tiers

Voici la classification du site officiel , En fait, ces concepts ont quelques points communs .

  1. Intergiciels au niveau de l'application

Utiliser app.use Méthode ou app.METHOD(MethodReprésentation http Méthodes,C'est - à - dire: get/post Attendez.)Lié à app Middleware on Object .

const app = express();

//  Middleware sans chemin de montage , Chaque demande passe par cet intergiciel 
app.use(function (req, res, next) {
    
  console.log('Time:', Date.now())
  next()
});
app.use('/user/:id', function (req, res, next) {
    
  console.log('Request Type:', req.method);
});

Appelé dans le premier intergiciel next Méthodes, Il va donc passer au deuxième intergiciel , Le deuxième parce qu'il n'y a pas d'appel next Méthodes, Aucun des intergiciels suivants n'exécutera .

  1. Middleware de niveau routage

Et Koa C'est différent., Le routage est Express Une partie de,Généralement par router.use Méthode de liaison à router Objet:

const app = express();
const router = express.Router();

//  Montage de l'intergiciel vers  /1ogin Sous le chemin,Toutes les visites /1ogin  Toutes les demandes passent par cet intergiciel 
router.use('/login', function (req, res, next) {
    
  console.log('Time:', Date.now())
  next();
});
  1. Intergiciel de niveau d'erreur

Les intergiciels de gestion des erreurs sont: 4 Paramètres, Même s'il n'est pas nécessaire de passer next Méthode pour appeler le prochain intergiciel , Il doit également être déclaré dans la liste des paramètres , Sinon, l'intergiciel sera identifié comme un intergiciel régulier , Impossible de traiter les erreurs .

app.use(function (err, req, res, next) {
    
  console.error(err.stack);
  res.status(500).send('Something broke!');
});
  1. Intergiciel intégré

De 4.x Début de la version,Express Ne dépend plus Connect C'est. En plus de gérer les ressources statiques static Hors module,Express Les intergiciels précédemment intégrés sont maintenant tous installés séparément en tant que modules .

  1. Intergiciels tiers

Les intergiciels tiers peuvent être Express L'application ajoute plus de fonctionnalités ,Généralement par npm Pour installer,Par exemple, obtenir Cookie Information commune cookie-parser Module, Ou pour analyser le formulaire bodyParser Attendez..

Koa Pas de middleware intégré , Même le routage n'est pas inclus , Tous les intergiciels sont implémentés par des modules tiers ,Par rapport à Express Allez, viens.,C'est plus comme ça. Connect..

3.5 next Méthodes

Que ce soit Express Toujours Koa, Les appels de middleware passent par next Méthode d'exécution, La méthode a été utilisée pour la première fois Connect Proposé par,Et par Express Et Koa À suivre.

Quand on appelle app.use La méthode, Un tableau d'intergiciels est formé à l'intérieur , À l'intérieur du cadre, l'exécution du prochain intergiciel est placée à next Méthode interne,Quand nous effectuons next La méthode, Le prochain intergiciel sera exécuté . S'il n'y a pas d'appel dans un intergiciel next Méthodes, Alors l'appel de l'intergiciel sera interrompu , Aucun des intergiciels suivants ne sera exécuté .

Pour l'ensemble de l'application,next La mise en œuvre de la méthode n'est rien d'autre qu'un appel imbriqué , Peut également être compris comme une opération récursive ,Fin de la mise en œuvre next Après le middleware correspondant , Il retourne également à l'intérieur de la méthode originale , Continuez avec la méthode suivante .

Comme le montre la figure ci - dessous,Celle ci - dessous.“ Carte des oignons ” C'est très visuel. Koa Comment fonctionne l'intergiciel ,Pour request Objet, Commencez par l'intergiciel ultrapériphérique et descendez , Après avoir atteint l'intergiciel le plus bas , Retourner au client de l'intérieur à l'extérieur . Chaque Middleware peut être request Ou response Modification de l'objet.

3.6 Appel série de l'intergiciel

Ce qui suit est Koa Éléments de base de la conception ,In Web En cours de développement, Nous voulons généralement que certaines opérations puissent être effectuées en série , Par exemple, attendre que le Journal d'écriture soit terminé avant d'effectuer l'opération de base de données , Enfin, le routage .

Au niveau technique, Le scénario d'affaires ci - dessus se présente comme un appel en série à certains intergiciels asynchrones . Une façon plus facile de penser est de mettre next La méthode est mise dans le rappel .

Le code suivant définit deux Express Middleware, Contrairement à ce qui s'est passé auparavant, le deuxième intergiciel a appelé process.nextTick() Indique qu'il s'agit d'une opération asynchrone .

const app = require('express')();
app.use(function (req, res, next) {
    
  next();
  console.log("I am middleware1 ");
});
app.use(function (req, res, next) {
    
  process.nextTick(function () {
    
    console.log("I am middleware2");
    next();
  });
});
app.listen(3000);
// Accès àlocalhost:3000Résultats de la production pour
// I am middleware1
// I am middleware2

Selon le principe ci - dessus,next La méthode retourne à l'intergiciel supérieur après l'exécution , Il faut d'abord l'exécuter. middleware2,Et ensuite middleware1; Mais à cause du deuxième intergiciel process.nextTick C'est un appel asynchrone, Alors revenez immédiatement au premier intergiciel ,Continuer la sortie I am middleware1, Ensuite, la fonction de rappel de middleware II exécute ,Produits I am middleware2.

Nous l'avons déjà mentionné.,Dans certains cas, Nous aimerions peut - être attendre middleware2 Sortie des résultats après l'exécution .Et Koa Moyenne,Aide async / await Méthodes, C'est devenu facile. .

const Koa = require("Koa");
const app = new Koa();
app.use(async (ctx, next) => {
    
  await next()
  console.log("I am middlewarel ");
});
app.use(async (ctx, next) => {
    
  process.nextTick(function () {
    
    console.log("I am middleware2")
    next();
  });
});
app.listen(3000);
// Accès àlocalhost:3000Résultats de la production pour
// I am middleware2
// I am middleware1

Utiliser await Après mot - clé,Jusqu'à next Avant que la méthode asynchrone interne ne soit terminée ,midddlware1 Ne descend pas .

Voici une analyse d'un exemple concret , Cet exemple reflète un besoin commun , C'est - à - dire définir l'ensemble app Temps de réponse pour.

3.7 Un exemple:Comment réaliser la réponse timeout

  1. Express Timeout response in

Voici un exemple plus proche d'une entreprise spécifique .In Web En cours de développement, Nous nous attendions à ce que des messages d'erreur spécifiques soient retournés pour les demandes qui n'ont pas été traitées depuis longtemps .

Si c'est dans Express Moyenne,Peut être utilisé connect-timeout Cet intergiciel tiers pour traiter les délais de réponse , L'implémentation de l'intergiciel est simple ,Voici un paragraphe qui utilise connect-timeout Code schématique pour la réponse timeout .

const express = require('express');
const timeout = require('connect-timeout');

// example of using this top-level; note the use of haltonTimedout
// after every middleware; it will stop the request flow on a timeout
const app = express();
app.use(timeout('5s'));
app.use(some middleware);
app.use(haltOnTimedout);
app.use(some middleware);
app.use(haltOnTimedout);

function haltonTimedout(req, res, next) {
    
  if (!reg.timedout) next();
}

app.listen(3000);

La mise en œuvre de cet intergiciel est simple ,timeout Une méthode de minuterie est définie en interne , Si le délai prescrit par le minuteur est dépassé , Déclenche un événement d'erreur et renvoie un 503 Code d'état,Et haltOnTimedout L'intergiciel suivant n'est plus exécuté . Si la réponse est terminée avant le déclenchement du minuteur , Le minuteur sera annulé. .

Bien que cela semble résoudre le problème des temps d'arrêt , Mais il est aussi évident d'y réfléchir avec soin ,In timeout Un seul minuteur simple est défini dans la méthode , Si l'intergiciel contient une opération asynchrone , Il est si facile d'avoir des problèmes en appelant la méthode de rappel .

Hypothèses timeout Après le chargement, un autre queryDB Middleware for, L'intergiciel encapsule une opération asynchrone de base de données , Et renvoie le résultat de la requête comme message de réponse .

queryDB Dans la plupart des cas, c'est rapide (1En quelques secondes(C'est fait., Mais parfois, pour une raison ou une autre ( Par exemple, bloqué par d'autres opérations ) Ce qui fait que le temps d'exécution devient 10 Secondes,À ce moment - là, timeout L'intergiciel a retourné l'information sur le temps d'arrêt au client ,SiqueryDB L'intérieur contient un res.send Méthodes,Ça va arriver Can't set headers after they are sent Erreur.

Pour résoudre ce problème, La meilleure façon est d'écouter les événements , Si l'événement est déclenché après un délai , Toutes les opérations après annulation ,Ou modifier directementres.end Méthodes,Mettez - en un flag Utilisé pour déterminer si .

La cause profonde du problème ci - dessus est connect-time,Ou Express Il n'y a aucun moyen de bien contrôler l'exécution des intergiciels asynchrones .

  1. Koa Timeout response in

Aide async L'intergiciel de la méthode est exécuté dans l'ordre , C'est parti. timeout La gestion est plus pratique , Actuellement, la communauté a également koa-timeout Attendez quelques intergiciels. , Le lecteur peut explorer et utiliser , Vous pouvez également envisager de vous réaliser vous - même , Après tout, la mise en oeuvre d'un tel intergiciel n'est pas si difficile .

Voici un exemple de ma propre réalisation ,L'idée centrale est d'utiliser promise.race Méthodes de comparaison setTimeout Et lequel des intergiciels suivants complétera plus rapidement .

app.use(async (ctx, next) => {
    
  let tmr = null;
  const timeout = 5000; // Réglage du temps d'arrêt
  await Promise.race([
    new Promise(function (resolve, reject) {
    
      tmr = setTimeout(function () {
    
        const e = new Error('Request timeout');
        e.status = 408;
        reject(e);
      }, timeout);
    }),
    new Promise(function (resolve, reject) {
    
      //  Exécuter le middleware chargé plus tard 
      (async function () {
    
        await next();
        clearTimeout(tmr);
        resolve();
      })();
    })
  ])
});

Si nous voulons contrôler les temps d'arrêt avec le code ci - dessus ,queryDB Besoin de retourner unPromise Objet ou async Méthodes.

原网站

版权声明
本文为[Cheyenne.]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/180/202206290206463251.html

随机推荐