Dezember 21, 2025
17 Min. Lesezeit

Junior Backend Entwickler (Node.js) Interview Fragen: Der komplette Leitfaden

interview
career-advice
job-search
entry-level
Junior Backend Entwickler (Node.js) Interview Fragen: Der komplette Leitfaden
MB

Milad Bonakdar

Autor

Meistern Sie die Node.js Backend-Entwicklung mit 35 essentiellen Interviewfragen, die JavaScript-Grundlagen, asynchrone Programmierung, Express.js, Datenbanken, APIs, Sicherheit und mehr abdecken. Perfekte Vorbereitung für Junior Backend Entwickler Interviews.


Einführung

Dieser umfassende Leitfaden enthält 35 sorgfältig ausgewählte Fragen für Vorstellungsgespräche, die die Grundlagen der Node.js-Backend-Entwicklung abdecken. Dies sind die Fragen, denen Junior-Backend-Entwickler tatsächlich in Vorstellungsgesprächen begegnen. Jede Frage enthält eine ausführliche Antwort, eine Seltenheitsbewertung und eine Schwierigkeitsbewertung, die auf der Analyse von Hunderten von echten Vorstellungsgesprächen von großen Technologieunternehmen und Startups basiert.

Egal, ob du dich auf deine erste Backend-Rolle vorbereitest oder von der Frontend-Entwicklung wechselst, dieser Leitfaden deckt alles ab, von JavaScript-Grundlagen über API-Design, Datenbankverwaltung, Sicherheitsbest Practices bis hin zu Bereitstellungsstrategien.


JavaScript-Grundlagen (8 Fragen)

1. Erkläre den Unterschied zwischen var, let und const in JavaScript

Antwort:

  • var: Funktionsbereich, wird hochgezogen und mit undefined initialisiert, kann im selben Bereich neu deklariert werden, in modernem Code weitgehend veraltet
  • let: Blockbereich, wird hochgezogen, verbleibt aber bis zur Deklaration in der Temporal Dead Zone (TDZ), kann nicht im selben Bereich neu deklariert werden, kann neu zugewiesen werden
  • const: Blockbereich, wird hochgezogen, befindet sich aber in der TDZ, muss bei der Deklaration initialisiert werden, kann nicht neu zugewiesen werden (aber Objekt-/Array-Inhalte können verändert werden)

Beispiel:

// var - Funktionsbereich
function example() {
  if (true) {
    var x = 1;
  }
  console.log(x); // 1 (außerhalb des Blocks zugänglich)
}

// let - Blockbereich
if (true) {
  let y = 2;
}
console.log(y); // ReferenceError

// const - kann nicht neu zugewiesen werden
const z = 3;
z = 4; // TypeError

const obj = { name: 'John' };
obj.name = 'Jane'; // OK - Eigenschaft wird verändert
obj = {}; // TypeError - kann nicht neu zugewiesen werden

Best Practice: Verwende standardmäßig const, let, wenn du neu zuweisen musst, verwende niemals var in modernem JavaScript.

Seltenheit: Häufig
Schwierigkeit: Einfach


2. Was sind Closures und gib ein praktisches Beispiel in Node.js?

Antwort: Ein Closure entsteht, wenn eine innere Funktion Zugriff auf Variablen aus dem Gültigkeitsbereich ihrer äußeren (umschließenden) Funktion hat, auch nachdem die äußere Funktion zurückgekehrt ist. Die innere Funktion "schließt" diese Variablen ein.

Praktisches Node.js-Beispiel:

// Middleware-Factory-Muster
function createAuthMiddleware(secretKey) {
  // secretKey wird von der zurückgegebenen Funktion "eingeschlossen"
  return function(req, res, next) {
    const token = req.headers.authorization;
    if (validateToken(token, secretKey)) {
      next();
    } else {
      res.status(401).json({ error: 'Nicht autorisiert' });
    }
  };
}

// Verwendung
const authMiddleware = createAuthMiddleware(process.env.JWT_SECRET);
app.use('/api/protected', authMiddleware);

Vorteile:

  • Datenschutz (secretKey kann nicht direkt aufgerufen werden)
  • Funktionsfabriken
  • Implementierung des Modulmusters
  • Beibehalten des Zustands in asynchronen Operationen

Seltenheit: Häufig
Schwierigkeit: Mittel


3. Erkläre das Schlüsselwort this und wie es sich in Pfeilfunktionen unterscheidet

Antwort: this bezieht sich auf den Ausführungskontext. Sein Wert hängt davon ab, WIE die Funktion aufgerufen wird.

Reguläre Funktionen:

const obj = {
  name: "Server",
  greet: function() {
    console.log(this.name); // "Server"
  }
};
obj.greet(); // this = obj

const greet = obj.greet;
greet(); // this = undefined (strikter Modus) oder global

Pfeilfunktionen:

const obj = {
  name: "Server",
  greet: () => {
    console.log(this.name); // undefined (lexikalischer Gültigkeitsbereich)
  }
};
obj.greet(); // this = lexikalischer Gültigkeitsbereich (Modulbereich in Node.js)

Hauptunterschied: Pfeilfunktionen haben kein eigenes this - sie erben es vom umschließenden Gültigkeitsbereich.

Seltenheit: Häufig
Schwierigkeit: Mittel


4. Was sind Promises und wie unterscheiden sie sich von Callbacks?

Antwort: Ein Promise repräsentiert den eventuellen Abschluss (oder Misserfolg) einer asynchronen Operation.

Callback-Muster (Callback-Hölle):

getUser(userId, (err, user) => {
  if (err) return handleError(err);
  getPosts(user.id, (err, posts) => {
    if (err) return handleError(err);
    getComments(posts[0].id, (err, comments) => {
      if (err) return handleError(err);
      // Verschachtelte Callbacks - schwer zu lesen
    });
  });
});

Promise-Muster:

getUser(userId)
  .then(user => getPosts(user.id))
  .then(posts => getComments(posts[0].id))
  .then(comments => console.log(comments))
  .catch(err => handleError(err));

Vorteile:

  • Vermeidet Callback-Hölle
  • Besseres Fehlerhandling mit .catch()
  • Verkettbare Operationen
  • Kann Promise.all() für parallele Operationen verwenden

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


5. Was ist async/await und wie verbessert es die Lesbarkeit des Codes?

Antwort: async/await ist syntaktischer Zucker, der auf Promises aufbaut und asynchronen Code mehr wie synchronen Code aussehen und sich auch so verhalten lässt.

Beispiel:

// Mit Promises
function fetchUserData(userId) {
  return fetchUser(userId)
    .then(user => {
      return fetchPosts(user.id)
        .then(posts => {
          return { user, posts };
        });
    })
    .catch(error => console.error(error));
}

// Mit async/await (sauberer)
async function fetchUserData(userId) {
  try {
    const user = await fetchUser(userId);
    const posts = await fetchPosts(user.id);
    return { user, posts };
  } catch (error) {
    console.error(error);
  }
}

Wichtige Punkte:

  • async-Funktion gibt immer ein Promise zurück
  • await pausiert die Ausführung, bis das Promise aufgelöst ist
  • Verwende try/catch für das Fehlerhandling
  • Macht sequentielle Operationen übersichtlicher

Seltenheit: Häufig
Schwierigkeit: Mittel


6. Erkläre Destrukturierung für Objekte und Arrays

Antwort: Destrukturierung extrahiert Werte aus Arrays oder Eigenschaften aus Objekten in separate Variablen.

Array-Destrukturierung:

const [first, second, ...rest] = [1, 2, 3, 4, 5];
// first = 1, second = 2, rest = [3, 4, 5]

// Elemente überspringen
const [primary, , tertiary] = ['red', 'green', 'blue'];
// primary = 'red', tertiary = 'blue'

Objekt-Destrukturierung:

const user = { name: 'Alice', age: 25, email: '[email protected]' };

const { name, age, city = 'NYC' } = user;
// name = 'Alice', age = 25, city = 'NYC' (Standardwert)

// Variablen umbenennen
const { name: userName, age: userAge } = user;

// Verschachtelte Destrukturierung
const { address: { street, zip } } = person;

Funktionsparameter:

function createUser({ name, email, role = 'user' }) {
  // Verwende destrukturierte Parameter
}

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


7. Was ist der Spread-Operator und was sind Rest-Parameter?

Antwort:

Spread-Operator (...) - Erweitert Iterables:

// Arrays
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

// Objekte (flache Kopie)
const user = { name: 'Alice', age: 25 };
const updatedUser = { ...user, age: 26 }; // Unveränderliches Update

// Funktionsargumente
const numbers = [1, 2, 3];
Math.max(...numbers); // 3

Rest-Parameter (...) - Sammelt mehrere Elemente:

// Funktionsparameter
function sum(...numbers) {
  return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 10

// Array-Destrukturierung
const [first, ...remaining] = [1, 2, 3, 4];
// first = 1, remaining = [2, 3, 4]

Hauptunterschied: Spread erweitert, Rest sammelt.

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


8. Erkläre gängige Array-Methoden: map, filter, reduce, forEach

Antwort:

map - Transformiert jedes Element, gibt ein neues Array zurück:

const doubled = [1, 2, 3].map(x => x * 2); // [2, 4, 6]

filter - Behält Elemente bei, die die Bedingung erfüllen:

const evens = [1, 2, 3, 4].filter(x => x % 2 === 0); // [2, 4]

reduce - Reduziert auf einen einzelnen Wert:

const sum = [1, 2, 3].reduce((acc, val) => acc + val, 0); // 6
const grouped = users.reduce((acc, user) => {
  acc[user.role] = acc[user.role] || [];
  acc[user.role].push(user);
  return acc;
}, {});

forEach - Iteriert, ohne ein neues Array zurückzugeben:

[1, 2, 3].forEach(item => console.log(item));

Seltenheit: Häufig
Schwierigkeit: Einfach


Node.js-Grundlagen (7 Fragen)

9. Was ist Node.js und wie unterscheidet es sich von traditionellen serverseitigen Sprachen?

Antwort: Node.js ist eine JavaScript-Laufzeitumgebung, die auf der V8-JavaScript-Engine von Chrome aufbaut und es ermöglicht, JavaScript auf der Serverseite auszuführen.

Hauptunterschiede:

  • Single-Threaded Event Loop: Verwendet ein nicht-blockierendes I/O-Modell im Gegensatz zu Multi-Threaded Blocking I/O
  • Standardmäßig asynchron: Operationen blockieren den Haupt-Thread nicht
  • JavaScript überall: Dieselbe Sprache für Frontend und Backend
  • NPM-Ökosystem: Größte Paketregistrierung der Welt
  • Schnelle Ausführung: V8-Engine kompiliert JavaScript in nativen Maschinencode

Wann sollte man Node.js verwenden:

  • Echtzeit-Anwendungen (Chat, Gaming)
  • API-Server
  • Microservices
  • Daten-Streaming-Anwendungen
  • I/O-intensive Anwendungen

Wann NICHT verwenden:

  • CPU-intensive Aufgaben (Bildverarbeitung, Videokodierung)
  • Anwendungen, die komplexe Berechnungen erfordern

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


10. Erkläre den Event Loop in Node.js

Antwort: Der Event Loop ist der Mechanismus, der es Node.js ermöglicht, nicht-blockierende I/O-Operationen durchzuführen, obwohl es Single-Threaded ist.

Wie es funktioniert:

  1. Call Stack: Führt synchronen Code aus (LIFO)
  2. Node APIs: Behandeln asynchrone Operationen (fs, http, Timer)
  3. Callback Queue (Macrotasks): Enthält Callbacks von Node APIs
  4. Microtask Queue: Enthält Promise-Callbacks (höhere Priorität)
  5. Event Loop: Verschiebt Aufgaben von Queues zum Call Stack, wenn der Stack leer ist

Ausführungsreihenfolge:

console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => console.log('3'));

console.log('4');

// Ausgabe: 1, 4, 3, 2
// Erklärung:
// - Synchroner Code (1, 4) wird zuerst ausgeführt
// - Microtasks (Promise) werden vor Macrotasks ausgeführt
// - Macrotasks (setTimeout) werden zuletzt ausgeführt

Phasen des Event Loops:

  1. Timer (setTimeout, setInterval)
  2. Ausstehende Callbacks
  3. Leerlauf, Vorbereitung
  4. Poll (Abrufen neuer I/O-Ereignisse)
  5. Check (setImmediate-Callbacks)
  6. Close-Callbacks

Seltenheit: Häufig
Schwierigkeit: Schwer


11. Was ist der Unterschied zwischen blockierendem und nicht-blockierendem Code?

Antwort:

Blockierender Code - Hält die Ausführung an, bis die Operation abgeschlossen ist:

// Synchroner Dateilesevorgang (blockiert)
const fs = require('fs');
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data); // Wartet auf das Lesen der Datei
console.log('Fertig'); // Wird nach dem Lesen der Datei ausgeführt

Nicht-blockierender Code - Setzt die Ausführung fort, behandelt das Ergebnis über einen Callback:

// Asynchroner Dateilesevorgang (nicht-blockierend)
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});
console.log('Fertig'); // Wird sofort ausgeführt, bevor das Lesen der Datei abgeschlossen ist

Warum nicht-blockierend wichtig ist:

  • Der Server kann mehrere Anfragen gleichzeitig bearbeiten
  • Bessere Ressourcenauslastung
  • Verbesserte Leistung für I/O-Operationen
  • Skalierbarkeit

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


12. Was sind Node.js-Module und wie funktioniert das Modulsystem?

Antwort: Node.js verwendet das CommonJS-Modulsystem (obwohl ES-Module ebenfalls unterstützt werden).

CommonJS (require/module.exports):

// math.js
function add(a, b) {
  return a + b;
}

module.exports = { add };
// oder
exports.add = add;

// app.js
const { add } = require('./math');
const result = add(2, 3);

ES-Module (import/export):

// math.js
export function add(a, b) {
  return a + b;
}

// app.js
import { add } from './math.js';

Modultypen:

  • Kernmodule: Eingebaut (fs, http, path)
  • Lokale Module: Deine eigenen Dateien
  • Drittanbieter-Module: Über npm installiert

Modul-Caching: Module werden nach dem ersten Require gecacht, sodass nachfolgende Requires dieselbe Instanz zurückgeben.

Seltenheit: Häufig
Schwierigkeit: Einfach


13. Erkläre den Unterschied zwischen process.nextTick() und setImmediate()

Antwort:

process.nextTick() - Führt den Callback in der aktuellen Phase aus, vor jeder anderen asynchronen Operation:

console.log('1');

process.nextTick(() => {
  console.log('2');
});

Promise.resolve().then(() => {
  console.log('3');
});

console.log('4');

// Ausgabe: 1, 4, 2, 3
// nextTick hat die höchste Priorität, sogar über Promises

setImmediate() - Führt den Callback in der nächsten Iteration des Event Loops aus:

console.log('1');

setImmediate(() => {
  console.log('2');
});

setTimeout(() => {
  console.log('3');
}, 0);

console.log('4');

// Ausgabe: 1, 4, 3, 2 (oder 1, 4, 2, 3 je nach Kontext)

Prioritätsreihenfolge:

  1. Synchroner Code
  2. process.nextTick()-Callbacks
  3. Promise-Callbacks (Microtasks)
  4. setTimeout(0) / setImmediate() (Macrotasks)

Anwendungsfälle:

  • nextTick: Stelle sicher, dass der Callback vor anderen asynchronen Operationen ausgeführt wird
  • setImmediate: Verschiebe die Ausführung auf die nächste Event-Loop-Iteration

Seltenheit: Selten
Schwierigkeit: Mittel-Schwer


14. Was ist das globale Objekt in Node.js?

Antwort: Das globale Objekt in Node.js ähnelt dem window-Objekt in Browsern, wird aber global genannt.

Globale Eigenschaften:

// Überall verfügbar, ohne Require
console.log(__dirname); // Aktueller Verzeichnispfad
console.log(__filename); // Aktueller Dateipfad
console.log(process); // Prozessobjekt
console.log(global); // Globales Objekt selbst

Gängige Globals:

  • process - Prozessinformationen und -steuerung
  • Buffer - Behandle Binärdaten
  • setTimeout, setInterval, clearTimeout, clearInterval
  • setImmediate, clearImmediate
  • console - Konsolenausgabe

Hinweis: In ES-Modulen sind __dirname und __filename standardmäßig nicht verfügbar. Verwende stattdessen import.meta.url.

Seltenheit: Häufig
Schwierigkeit: Einfach


15. Wie handhabst du Fehler in Node.js-Anwendungen?

Antwort: Das Fehlerhandling in Node.js kann über verschiedene Ansätze verwaltet werden:

1. Try-Catch für synchronen Code:

try {
  const data = fs.readFileSync('file.txt', 'utf8');
} catch (error) {
  console.error('Fehler beim Lesen der Datei:', error.message);
}

2. Callback-Fehlermuster:

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) {
    return console.error('Fehler:', err);
  }
  console.log(data);
});

3. Promise-Fehlerhandling:

fetchData()
  .then(data => processData(data))
  .catch(error => console.error('Fehler:', error));

4. Async/Await mit Try-Catch:

async function handleRequest() {
  try {
    const data = await fetchData();
    return data;
  } catch (error) {
    console.error('Fehler:', error);
    throw error; // Erneut werfen, falls erforderlich
  }
}

5. Globale Fehlerhandler:

// Unbehandelte Ausnahmen
process.on('uncaughtException', (error) => {
  console.error('Unbehandelte Ausnahme:', error);
  process.exit(1);
});

// Unbehandelte Promise-Ablehnungen
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unbehandelte Ablehnung:', reason);
});

6. Express-Fehlermiddleware:

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Etwas ist schiefgelaufen!' });
});

Seltenheit: Häufig
Schwierigkeit: Mittel


Express.js & Web-Frameworks (6 Fragen)

16. Was ist Express.js und was sind seine Hauptmerkmale?

Antwort: Express.js ist ein minimales und flexibles Node.js-Webanwendungs-Framework, das eine robuste Reihe von Funktionen zum Erstellen von Web- und mobilen Anwendungen bietet.

Hauptmerkmale:

  • Routing: Definiere Endpunkte und HTTP-Methoden
  • Middleware: Funktionen, die während des Request-Response-Zyklus ausgeführt werden
  • Template Engines: Rendere dynamisches HTML (EJS, Pug, Handlebars)
  • Fehlerhandling: Zentralisierte Fehlerhandlungs-Middleware
  • Statische Dateien: Stelle statische Assets bereit
  • JSON-Parsing: Eingebautes Body-Parsing für JSON- und URL-kodierte Daten

Grundlegendes Beispiel:

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

app.use(express.json());

app.get('/', (req, res) => {
  res.json({ message: 'Hallo Welt' });
});

app.listen(3000, () => {
  console.log('Server läuft auf Port 3000');
});

Warum Express:

  • Minimal und unvoreingenommen
  • Großes Ökosystem
  • Leicht zu erlernen
  • Flexibles Middleware-System

Seltenheit: Häufig
Schwierigkeit: Einfach


17. Was ist Middleware in Express.js? Gib Beispiele an.

Antwort: Middleware-Funktionen sind Funktionen, die Zugriff auf das Request-Objekt (req), das Response-Objekt (res) und die next-Funktion im Request-Response-Zyklus der Anwendung haben.

Middleware-Typen:

1. Application-Level Middleware:

app.use((req, res, next) => {
  console.log('Anfrage empfangen:', req.method, req.path);
  next(); // Übergib die Kontrolle an die nächste Middleware
});

2. Route-Level Middleware:

app.get('/users', authenticateUser, (req, res) => {
  res.json({ users: [] });
});

3. Error-Handling Middleware:

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: err.message });
});

4. Built-in Middleware:

app.use(express.json()); // Parse JSON-Bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-kodierte Daten
app.use(express.static('public')); // Stelle statische Dateien bereit

5. Third-Party Middleware:

const cors = require('cors');
const helmet = require('helmet');

app.use(cors());
app.use(helmet());

Beispiel für benutzerdefinierte Authentifizierungs-Middleware:

function authenticateUser(req, res, next) {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ error: 'Kein Token bereitgestellt' });
  }
  // Token verifizieren
  req.user = decodedToken;
  next();
}

Seltenheit: Häufig
Schwierigkeit: Mittel


18. Erkläre Express Routing und wie man Routen organisiert

Antwort: Routing bezieht sich darauf, wie die Endpunkte (URIs) einer Anwendung auf Clientanfragen reagieren.

Grundlegendes Routing:

app.get('/users', (req, res) => {
  res.json({ users: [] });
});

app.post('/users', (req, res) => {
  const newUser = req.body;
  res.status(201).json(newUser);
});

app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.json({ user: { id: userId } });
});

app.put('/users/:id', (req, res) => {
  // Benutzer aktualisieren
});

app.delete('/users/:id', (req, res) => {
  // Benutzer löschen
});

Routenparameter:

app.get('/users/:userId/posts/:postId', (req, res) => {
  const { userId, postId } = req.params;
  // Greife auf Routenparameter zu
});

Query-Parameter:

app.get('/search', (req, res) => {
  const { q, page, limit } = req.query;
  // ?q=nodejs&page=1&limit=10
});

Organisieren von Routen mit Express Router:

// routes/users.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.json({ users: [] });
});

router.get('/:id', (req, res) => {
  res.json({ user: { id: req.params.id } });
});

module.exports = router;

// app.js
const userRoutes = require('./routes/users');
app.use('/api/users', userRoutes);

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


19. Wie handhabst du Datei-Uploads in Express?

Antwort: Datei-Uploads können mit Middleware wie multer behandelt werden.

Grundlegender Datei-Upload:

const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
  // req.file enthält Dateiinformationen
  res.json({ 
    filename: req.file.filename,
    originalname: req.file.originalname,
    size: req.file.size
  });
});

Mehrere Dateien:

app.post('/upload-multiple', upload.array('files', 10), (req, res) => {
  // req.files ist ein Array von Dateien
  res.json({ uploaded: req.files.length });
});

Benutzerdefinierte Speicherkonfiguration:

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, file.fieldname + '-' + uniqueSuffix);
  }
});

const upload = multer({ 
  storage: storage,
  limits: { fileSize: 5 * 1024 * 1024 }, // 5MB Limit
  fileFilter: (req, file, cb) => {
    if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
      cb(null, true);
    } else {
      cb(new Error('Nur JPEG und PNG erlaubt'));
    }
  }
});

Seltenheit: Häufig
Schwierigkeit: Mittel


20. Was ist CORS und wie handhabst du es in Express?

Antwort: CORS (Cross-Origin Resource Sharing) ist eine Sicherheitsfunktion, die es Webseiten erlaubt oder verbietet, Anfragen an eine andere Domain zu stellen als die, die die Webseite bereitstellt.

Problem: Browser blockieren standardmäßig Anfragen von http://localhost:3000 an http://localhost:4000 (unterschiedliche Ursprünge).

Lösung mit CORS-Middleware:

const cors = require('cors');

// Erlaube alle Ursprünge (nur für die Entwicklung)
app.use(cors());

// Konfiguriere bestimmte Ursprünge
app.use(cors({
  origin: 'https://example.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

// Mehrere Ursprünge
app.use(cors({
  origin: ['https://example.com', 'https://app.example.com']
}));

Manuelle CORS-Header:

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'https://example.com');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


21. Wie strukturierst du eine große Express.js-Anwendung?

Antwort: Organisiere Code in logische Module und Ordner, um die Wartbarkeit zu gewährleisten.

Empfohlene Struktur:

project/
├── src/
│   ├── controllers/
│   │   └── userController.js
│   ├── models/
│   │   └── User.js
│   ├── routes/
│   │   └── userRoutes.js
│   ├── middleware/
│   │   └── auth.js
│   ├── services/
│   │   └── userService.js
│   ├── utils/
│   │   └── helpers.js
│   ├── config/
│   │   └── database.js
│   └── app.js
├── tests/
├── .env
└── package.json

Beispiel für die Trennung von Verantwortlichkeiten:

Controller (behandelt HTTP):

// controllers/userController.js
const userService = require('../services/userService');

exports.getUsers = async (req, res, next) => {
  try {
    const users = await userService.getAllUsers();
    res.json(users);
  } catch (error) {
    next(error);
  }
};

Service (Geschäftslogik):

// services/userService.js
const User = require('../models/User');

exports.getAllUsers = async () => {
  return await User.find();
};

Routen:

// routes/userRoutes.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');

router.get('/', userController.getUsers);
router.post('/', userController.createUser);

module.exports = router;

App-Setup:

// app.js
const express = require('express');
const userRoutes = require('./routes/userRoutes');

const app = express();
app.use(express.json());
app.use('/api/users', userRoutes);

Seltenheit: Häufig
Schwierigkeit: Mittel


Datenbankkonzepte (5 Fragen)

22. Was ist der Unterschied zwischen SQL- und NoSQL-Datenbanken?

Antwort:

SQL (relationale) Datenbanken:

  • Strukturierte Daten mit Tabellen, Zeilen, Spalten
  • Das Schema muss vor der Verwendung definiert werden
  • ACID-Konformität (Atomicity, Consistency, Isolation, Durability)
  • Beispiele: PostgreSQL, MySQL, SQLite
  • Am besten geeignet für: Komplexe Abfragen, Transaktionen, strukturierte Daten

NoSQL-Datenbanken:

  • Flexibles Schema oder Schema-los
  • Verschiedene Datenmodelle (Dokument, Key-Value, Graph, Spalte)
  • Horizontale Skalierung
  • Beispiele: MongoDB, Redis, Cassandra
  • Am besten geeignet für: Groß angelegte Anwendungen, flexible Schemata, schnelle Entwicklung

Vergleich:

MerkmalSQLNoSQL
SchemaFestFlexibel
SkalierbarkeitVertikalHorizontal
ACIDJaVariiert
AbfragespracheSQLVariiert
BeziehungenJoinsEingebettet/Referenzen

Wann sollte man SQL verwenden:

  • Komplexe Abfragen und Beziehungen
  • ACID-Konformität erforderlich
  • Strukturierte Daten
  • Finanztransaktionen

Wann sollte man NoSQL verwenden:

  • Schnelle Entwicklung
  • Große Datenmengen
  • Flexible Schemaanforderungen
  • Einfache Abfragen

Seltenheit: Häufig
Schwierigkeit: Einfach-Mittel


23. Wie verbindet man sich in Node.js mit einer Datenbank? (MongoDB-Beispiel)

Antwort: Verwende MongoDB mit Mongoose als Beispiel:

Grundlegende Verbindung:

const mongoose = require('mongoose');

// Verbindungszeichenfolge
const mongoURI = 'mongodb://localhost:27017/mydb';

// Verbinden
mongoose.connect(mongoURI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
.then(() => console.log('MongoDB verbunden'))
.catch(err => console.error('Verbindungsfehler:', err));

Mit Umgebungsvariablen:

require('dotenv').config();

mongoose.connect(process.env.MONGODB_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

Verbindungsereignisse:

mongoose.connection.on('connected', () => {
  console.
Newsletter subscription

Wöchentliche Karrieretipps, die wirklich funktionieren

Erhalten Sie die neuesten Einblicke direkt in Ihr Postfach

Decorative doodle

Ihr nächstes Vorstellungsgespräch ist nur einen Lebenslauf entfernt

Erstellen Sie in wenigen Minuten einen professionellen, optimierten Lebenslauf. Keine Designkenntnisse erforderlich—nur bewährte Ergebnisse.

Meinen Lebenslauf erstellen

Diesen Beitrag teilen

Überwinden Sie die 75% ATS-Ablehnungsrate

3 von 4 Lebensläufen erreichen nie ein menschliches Auge. Unsere Keyword-Optimierung erhöht Ihre Erfolgsrate um bis zu 80% und stellt sicher, dass Recruiter Ihr Potenzial tatsächlich sehen.