Kattava opas TypeScript-väliohjelmistojen ymmärtämiseen ja toteuttamiseen Express.js-sovelluksissa. Tutustu edistyksellisiin tyyppikuvioihin vankan ja ylläpidettävän koodin saavuttamiseksi.
TypeScript-väliohjelmisto: Express-väliohjelmistotyyppikuvioiden hallinta
Express.js, minimalistinen ja joustava Node.js-verkkosovelluskehys, antaa kehittäjille mahdollisuuden rakentaa vankkoja ja skaalautuvia API:ita ja verkkosovelluksia. TypeScript parantaa Expressiä lisäämällä staattisen tyypityksen, parantamalla koodin ylläpidettävyyttä ja havaitsemalla virheet varhaisessa vaiheessa. Väliohjelmistofunktiot ovat Expressin kulmakivi, jonka avulla voit siepata ja käsitellä pyyntöjä ennen kuin ne saavuttavat reitinkäsittelijäsi. Tämä artikkeli tutkii edistyksellisiä TypeScript-tyyppikuvioita Express-väliohjelmistojen määrittämiseen ja hyödyntämiseen, mikä parantaa tyyppiturvallisuutta ja koodin selkeyttä.
Express-väliohjelmistojen ymmärtäminen
Väliohjelmistofunktiot ovat funktioita, joilla on pääsy pyyntöobjektiin (req), vastausobjektiin (res) ja seuraavaan väliohjelmistofunktioon sovelluksen pyyntö-vastaus-syklissä. Väliohjelmistofunktiot voivat suorittaa seuraavat tehtävät:
- Suorittaa mitä tahansa koodia.
- Tehdä muutoksia pyyntö- ja vastausobjekteihin.
- Lopettaa pyyntö-vastaus-sykli.
- Kutsua seuraavaa väliohjelmistofunktiota pinossa.
Väliohjelmistofunktiot suoritetaan peräkkäin, kun ne lisätään Express-sovellukseen. Yleisiä väliohjelmistojen käyttötapauksia ovat:
- Pyyntöjen kirjaaminen.
- Käyttäjien todennus.
- Resurssien käytön valtuuttaminen.
- Pyyntötietojen validoiminen.
- Virheiden käsittely.
Perus-TypeScript-väliohjelmisto
Perus-TypeScript-Express-sovelluksessa väliohjelmistofunktio voi näyttää tältä:
import { Request, Response, NextFunction } from 'express';
function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
console.log(`Pyyntö: ${req.method} ${req.url}`);
next();
}
export default loggerMiddleware;
Tämä yksinkertainen väliohjelmisto kirjaa pyynnön metodin ja URL-osoitteen konsoliin. Käydään läpi tyyppimääritykset:
Request: Edustaa Express-pyyntöobjektia.Response: Edustaa Express-vastausobjektia.NextFunction: Funktio, joka kutsuttaessa suorittaa seuraavan väliohjelmiston pinossa.
Voit käyttää tätä väliohjelmistoa Express-sovelluksessasi näin:
import express from 'express';
import loggerMiddleware from './middleware/loggerMiddleware';
const app = express();
const port = 3000;
app.use(loggerMiddleware);
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Palvelin kuuntelee portissa ${port}`);
});
Edistyneet tyyppikuviot väliohjelmistoille
Vaikka perus-väliohjelmistoesimerkki on toimiva, siitä puuttuu joustavuus ja tyyppiturvallisuus monimutkaisempiin skenaarioihin. Tutustutaan edistyneisiin tyyppikuvioihin, jotka parantavat väliohjelmistojen kehitystä TypeScriptillä.
1. Mukautetut pyyntö-/vastaustyypit
Usein sinun on laajennettava Request- tai Response-objekteja mukautetuilla ominaisuuksilla. Esimerkiksi todennuksen jälkeen saatat haluta lisätä user-ominaisuuden Request-objektiin. TypeScriptin avulla voit laajentaa olemassa olevia tyyppejä julistusten yhdistämisen avulla.
// src/types/express/index.d.ts
import { Request as ExpressRequest } from 'express';
declare global {
namespace Express {
interface Request {
user?: {
id: string;
email: string;
// ... muut käyttäjän ominaisuudet
};
}
}
}
export {}; // Tämä tarvitaan, jotta tiedostosta tulee moduuli
Tässä esimerkissä laajennamme Express.Request-rajapintaa sisältämään valinnaisen user-ominaisuuden. Nyt todennus-väliohjelmistossasi voit täyttää tämän ominaisuuden:
import { Request, Response, NextFunction } from 'express';
function authenticationMiddleware(req: Request, res: Response, next: NextFunction) {
// Simuloi todennuslogiikkaa
const userId = req.headers['x-user-id'] as string; // Tai hae tunnuksesta jne.
if (userId) {
// Todellisessa sovelluksessa hakisit käyttäjän tietokannasta
req.user = {
id: userId,
email: `user${userId}@example.com`
};
next();
} else {
res.status(401).send('Ei valtuuksia');
}
}
export default authenticationMiddleware;
Ja reitinkäsittelijöissäsi voit turvallisesti käyttää req.user-ominaisuutta:
import express from 'express';
import authenticationMiddleware from './middleware/authenticationMiddleware';
const app = express();
const port = 3000;
app.use(authenticationMiddleware);
app.get('/profile', (req: Request, res: Response) => {
if (req.user) {
res.send(`Hei, ${req.user.email}! Käyttäjätunnuksesi on ${req.user.id}`);
} else {
// Tämän ei pitäisi koskaan tapahtua, jos väliohjelmisto toimii oikein
res.status(500).send('Sisäinen palvelinvirhe');
}
});
app.listen(port, () => {
console.log(`Palvelin kuuntelee portissa ${port}`);
});
2. Väliohjelmistotehtaat
Väliohjelmistotehtaat ovat funktioita, jotka palauttavat väliohjelmistofunktioita. Tämä kuvio on hyödyllinen, kun sinun on määritettävä väliohjelmisto tietyillä asetuksilla tai riippuvuuksilla. Harkitse esimerkiksi lokitus-väliohjelmistoa, joka kirjaa viestit tiettyyn tiedostoon:
import { Request, Response, NextFunction } from 'express';
import fs from 'fs';
import path from 'path';
function createLoggingMiddleware(logFilePath: string) {
return (req: Request, res: Response, next: NextFunction) => {
const logMessage = `[${new Date().toISOString()}] Pyyntö: ${req.method} ${req.url}\n`;
fs.appendFile(logFilePath, logMessage, (err) => {
if (err) {
console.error('Virhe lokitiedostoon kirjoittamisessa:', err);
}
next();
});
};
}
export default createLoggingMiddleware;
Voit käyttää tätä väliohjelmistotehdasta näin:
import express from 'express';
import createLoggingMiddleware from './middleware/loggingMiddleware';
const app = express();
const port = 3000;
const logFilePath = path.join(__dirname, 'logs', 'requests.log');
app.use(createLoggingMiddleware(logFilePath));
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Palvelin kuuntelee portissa ${port}`);
});
3. Asynkroninen väliohjelmisto
Väliohjelmistofunktioiden on usein suoritettava asynkronisia toimintoja, kuten tietokantakyselyjä tai API-kutsuja. Jotta voit käsitellä asynkronisia toimintoja oikein, sinun on varmistettava, että next-funktiota kutsutaan asynkronisen toiminnon päätyttyä. Voit saavuttaa tämän käyttämällä async/await- tai Promise-objekteja.
import { Request, Response, NextFunction } from 'express';
async function asyncMiddleware(req: Request, res: Response, next: NextFunction) {
try {
// Simuloi asynkronista toimintoa
await new Promise(resolve => setTimeout(resolve, 100));
console.log('Asynkroninen toiminto suoritettu');
next();
} catch (error) {
next(error); // Välitä virhe virheenkäsittely-väliohjelmistolle
}
}
export default asyncMiddleware;
Tärkeää: Muista käsitellä virheet asynkronisessa väliohjelmistossasi ja välittää ne virheenkäsittely-väliohjelmistolle käyttämällä next(error). Tämä varmistaa, että virheet käsitellään ja kirjataan oikein.
4. Virheenkäsittely-väliohjelmisto
Virheenkäsittely-väliohjelmisto on erityinen väliohjelmistotyyppi, joka käsittelee virheet, jotka tapahtuvat pyyntö-vastaus-syklin aikana. Virheenkäsittely-väliohjelmistofunktioilla on neljä argumenttia: err, req, res ja next.
import { Request, Response, NextFunction } from 'express';
function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
console.error(err.stack);
res.status(500).send('Jotain meni pieleen!');
}
export default errorHandler;
Sinun on rekisteröitävä virheenkäsittely-väliohjelmisto kaikkien muiden väliohjelmistojen ja reitinkäsittelijöiden jälkeen. Express tunnistaa virheenkäsittely-väliohjelmiston neljän argumentin läsnäolon perusteella.
import express from 'express';
import asyncMiddleware from './middleware/asyncMiddleware';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(asyncMiddleware);
app.get('/', (req, res) => {
throw new Error('Simuloitu virhe!'); // Simuloi virhettä
});
app.use(errorHandler); // Virheenkäsittely-väliohjelmisto TÄYTYY rekisteröidä viimeisenä
app.listen(port, () => {
console.log(`Palvelin kuuntelee portissa ${port}`);
});
5. Pyyntöjen validointi-väliohjelmisto
Pyyntöjen validointi on olennainen osa turvallisten ja luotettavien API:iden rakentamista. Väliohjelmistoa voidaan käyttää saapuvien pyyntötietojen validoimiseen ja varmistamaan, että ne täyttävät tietyt kriteerit ennen kuin ne saavuttavat reitinkäsittelijäsi. Kirjastoja, kuten joi tai express-validator, voidaan käyttää pyyntöjen validointiin.
Tässä on esimerkki express-validator-käytöstä:
import { Request, Response, NextFunction } from 'express';
import { body, validationResult } from 'express-validator';
const validateCreateUserRequest = [
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
}
];
export default validateCreateUserRequest;
Tämä väliohjelmisto validoi email- ja password-kentät pyyntöjen rungossa. Jos validointi epäonnistuu, se palauttaa 400 Bad Request -vastauksen, jossa on joukko virheilmoituksia. Voit käyttää tätä väliohjelmistoa reitinkäsittelijöissäsi näin:
import express from 'express';
import validateCreateUserRequest from './middleware/validateCreateUserRequest';
const app = express();
const port = 3000;
app.post('/users', validateCreateUserRequest, (req, res) => {
// Jos validointi onnistuu, luo käyttäjä
res.send('Käyttäjä luotu onnistuneesti!');
});
app.listen(port, () => {
console.log(`Palvelin kuuntelee portissa ${port}`);
});
6. Riippuvuuksien injektointi väliohjelmistolle
Kun väliohjelmistofunktiosi riippuvat ulkoisista palveluista tai määrityksistä, riippuvuuksien injektointi voi auttaa parantamaan testattavuutta ja ylläpidettävyyttä. Voit käyttää riippuvuuksien injektointikonttia, kuten tsyringe, tai yksinkertaisesti välittää riippuvuudet argumentteina väliohjelmistotehtaille.
Tässä on esimerkki väliohjelmistotehtaasta riippuvuuksien injektoinnilla:
// src/services/UserService.ts
export class UserService {
async createUser(email: string, password: string): Promise {
// Todellisessa sovelluksessa tallentaisit käyttäjän tietokantaan
console.log(`Luodaan käyttäjä sähköpostilla: ${email} ja salasanalla: ${password}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Simuloi tietokantatoimintoa
}
}
// src/middleware/createUserMiddleware.ts
import { Request, Response, NextFunction } from 'express';
import { UserService } from '../services/UserService';
function createCreateUserMiddleware(userService: UserService) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const { email, password } = req.body;
await userService.createUser(email, password);
res.status(201).send('Käyttäjä luotu onnistuneesti!');
} catch (error) {
next(error);
}
};
}
export default createCreateUserMiddleware;
// src/app.ts
import express from 'express';
import createCreateUserMiddleware from './middleware/createUserMiddleware';
import { UserService } from './services/UserService';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(express.json()); // Jäsennä JSON-pyyntöjen rungot
const userService = new UserService();
const createUserMiddleware = createCreateUserMiddleware(userService);
app.post('/users', createUserMiddleware);
app.use(errorHandler);
app.listen(port, () => {
console.log(`Palvelin kuuntelee portissa ${port}`);
});
Parhaat käytännöt TypeScript-väliohjelmistoille
- Pidä väliohjelmistofunktiot pieninä ja kohdennettuina. Jokaisella väliohjelmistofunktiolla tulisi olla yksi vastuu.
- Käytä kuvaavia nimiä väliohjelmistofunktioillesi. Nimen tulisi selvästi osoittaa, mitä väliohjelmisto tekee.
- Käsittele virheet oikein. Ota aina kiinni virheet ja välitä ne virheenkäsittely-väliohjelmistolle käyttämällä
next(error). - Käytä mukautettuja pyyntö-/vastaustyyppejä parantamaan tyyppiturvallisuutta. Laajenna
Request- jaResponse-rajapintoja tarpeen mukaan mukautetuilla ominaisuuksilla. - Käytä väliohjelmistotehtaita määrittämään väliohjelmisto tietyillä asetuksilla.
- Dokumentoi väliohjelmistofunktiosi. Selitä, mitä väliohjelmisto tekee ja miten sitä tulisi käyttää.
- Testaa väliohjelmistofunktiosi perusteellisesti. Kirjoita yksikkötestejä varmistaaksesi, että väliohjelmistofunktiosi toimivat oikein.
Johtopäätös
TypeScript parantaa merkittävästi Express-väliohjelmistojen kehitystä lisäämällä staattisen tyypityksen, parantamalla koodin ylläpidettävyyttä ja havaitsemalla virheet varhaisessa vaiheessa. Hallitsemalla edistyneitä tyyppikuvioita, kuten mukautettuja pyyntö-/vastaustyyppejä, väliohjelmistotehtaita, asynkronista väliohjelmistoa, virheenkäsittely-väliohjelmistoa ja pyyntöjen validointi-väliohjelmistoa, voit rakentaa vankkoja, skaalautuvia ja tyyppiturvallisia Express-sovelluksia. Muista noudattaa parhaita käytäntöjä pitääksesi väliohjelmistofunktiosi pieninä, kohdennettuina ja hyvin dokumentoituina.