Bird
Raised Fist0
Expressframework~10 mins

Dependency injection in Express - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Dependency injection in Express
Create dependencies
↓
Inject dependencies into middleware or routes
↓
Express app uses injected dependencies
↓
Handle requests using injected services
↓
Send response
This flow shows how dependencies are created, injected into Express routes or middleware, and then used to handle requests.
Execution Sample
Express
const express = require('express');
const app = express();

const logger = { log: msg => console.log('LOG:', msg) };

app.get('/', (req, res) => {
  logger.log('Home route accessed');
  res.send('Hello');
});
This code creates a logger dependency and injects it into the route handler to log messages when the route is accessed.
Execution Table
StepActionDependency StateEffect
1Create logger objectlogger = { log: function }Logger ready to use
2Define route '/' with injected loggerlogger available in routeRoute can call logger.log
3Request to '/' receivedlogger unchangedRoute handler runs
4Call logger.log('Home route accessed')logger logs messageConsole shows: LOG: Home route accessed
5Send response 'Hello'logger unchangedClient receives 'Hello'
6Request handled fullyNo changesWaiting for next request
💡 Request completes after response is sent, dependency remains ready for next use
Variable Tracker
VariableStartAfter Step 1After Step 3After Step 5Final
loggerundefined{ log: function }{ log: function }{ log: function }{ log: function }
requndefinedundefined{ request object }{ request object }undefined
resundefinedundefined{ response object }{ response object }undefined
Key Moments - 3 Insights
Why does the logger object stay the same throughout the request?
Because the logger is created once and injected as a shared dependency; it is not recreated per request (see execution_table steps 1 and 3).
How does the route handler access the logger dependency?
The logger is available in the route's scope because it was defined outside and used inside the route callback (execution_table step 2).
What happens if we modify the logger inside a request?
Modifying the logger would affect all future requests since it's shared; typically, dependencies are kept stateless or carefully managed (not shown in this example).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the state of 'logger' after step 3?
AUndefined
BAn object with a log function
CA string message
DNull
💡 Hint
Check the 'Dependency State' column at step 3 in the execution_table
At which step does the console output 'LOG: Home route accessed' appear?
AStep 5
BStep 2
CStep 4
DStep 6
💡 Hint
Look at the 'Effect' column describing console output in the execution_table
If the logger was recreated inside the route handler, how would the variable tracker change?
ALogger would have different instances after each request
BLogger would be null after step 3
CLogger would be undefined at start and after step 1
DLogger would not appear in variable tracker
💡 Hint
Consider how variable values change when a new object is created per request, referencing variable_tracker
Concept Snapshot
Dependency injection in Express:
- Create dependencies (e.g., services, loggers) outside routes
- Inject them by referencing in route handlers or middleware
- Allows easy reuse and testing
- Keeps code clean and modular
- Dependencies stay consistent across requests unless recreated
Full Transcript
Dependency injection in Express means creating reusable objects like loggers or services outside route handlers and then using them inside routes. This way, the same dependency is shared and used whenever a request comes in. The flow starts by creating dependencies, then injecting them into routes, handling requests using these dependencies, and finally sending responses. The example shows a logger object created once and used inside a route to log messages when the route is accessed. The logger remains the same across requests, ensuring consistent behavior. This approach helps keep code organized and easy to test.

Practice

(1/5)
1. What is the main purpose of dependency injection in an Express app?
easy
A. To provide parts of the app with the resources they need without hardcoding them
B. To make the app run faster by caching data
C. To automatically generate routes based on file names
D. To handle errors globally in the app

Solution

  1. Step 1: Understand dependency injection concept

    Dependency injection means giving parts of your app what they need instead of making them find it themselves.
  2. Step 2: Identify the purpose in Express

    In Express, this helps keep code organized and flexible by passing dependencies explicitly.
  3. Final Answer:

    To provide parts of the app with the resources they need without hardcoding them -> Option A
  4. Quick Check:

    Dependency injection = Provide needed resources [OK]
Hint: Think: "Give what is needed, don't make it find" [OK]
Common Mistakes:
  • Confusing dependency injection with caching
  • Thinking it auto-generates routes
  • Mixing it with error handling
2. Which of the following is the correct way to inject a service into an Express router?
easy
A. const router = express.Router(); router.use(service);
B. const router = express.Router(service);
C. function createRouter(service) { const router = express.Router(); router.service = service; return router; }
D. const router = express.Router(); router.service = service();

Solution

  1. Step 1: Check how to pass dependencies in Express

    Express.Router() does not accept parameters directly, so passing service as argument is invalid.
  2. Step 2: Use a factory function to inject service

    Creating a function that takes service and returns a router with service attached is the correct pattern.
  3. Final Answer:

    function createRouter(service) { const router = express.Router(); router.service = service; return router; } -> Option C
  4. Quick Check:

    Inject by factory function = function createRouter(service) { const router = express.Router(); router.service = service; return router; } [OK]
Hint: Use a function to pass dependencies, not Router constructor [OK]
Common Mistakes:
  • Passing service directly to express.Router()
  • Calling service as a middleware incorrectly
  • Assigning service without a factory function
3. Consider this code snippet:
function createService() {
  return { getName: () => 'MyService' };
}

function createRouter(service) {
  const router = require('express').Router();
  router.get('/name', (req, res) => {
    res.send(service.getName());
  });
  return router;
}

const service = createService();
const router = createRouter(service);

// What happens when a GET request is made to '/name'?
medium
A. The server will crash due to missing middleware
B. The response will be undefined
C. There will be a runtime error because service is not defined
D. The response will be 'MyService'

Solution

  1. Step 1: Analyze service creation

    The createService function returns an object with getName method returning 'MyService'.
  2. Step 2: Analyze router handler

    The router uses the injected service and calls getName to send the response on '/name' route.
  3. Final Answer:

    The response will be 'MyService' -> Option D
  4. Quick Check:

    Injected service method returns 'MyService' [OK]
Hint: Injected service methods run as expected in route handlers [OK]
Common Mistakes:
  • Assuming service is undefined inside handler
  • Thinking service causes runtime error
  • Confusing middleware with service injection
4. You have this code snippet:
function createRouter(service) {
  const router = require('express').Router();
  router.get('/data', (req, res) => {
    res.send(service.getData());
  });
  return router;
}

const router = createRouter();
What is the main issue here?
medium
A. The router is missing the service argument, causing service to be undefined
B. The router should be created with express() instead of express.Router()
C. The getData method is not defined on the router
D. The route path '/data' is invalid in Express

Solution

  1. Step 1: Check function call for createRouter

    The createRouter function expects a service argument, but none is passed, so service is undefined.
  2. Step 2: Understand impact on route handler

    Calling service.getData() will cause a runtime error because service is undefined.
  3. Final Answer:

    The router is missing the service argument, causing service to be undefined -> Option A
  4. Quick Check:

    Missing dependency argument = undefined service [OK]
Hint: Always pass dependencies when calling factory functions [OK]
Common Mistakes:
  • Thinking express() should replace express.Router() here
  • Confusing method definition with dependency injection
  • Assuming route path is invalid
5. You want to inject a database client into multiple routers in your Express app. Which approach best supports this using dependency injection?
hard
A. Use a global variable for the database client and import it in each router file
B. Create a factory function for each router that accepts the database client and returns a configured router
C. Attach the database client directly to the Express app instance and access it via req.app
D. Create middleware that initializes the database client on every request

Solution

  1. Step 1: Understand dependency injection best practice

    Injecting dependencies via factory functions keeps routers independent and testable.
  2. Step 2: Evaluate options for injecting database client

    Factory functions allow passing the client explicitly to each router, avoiding globals and repeated initialization.
  3. Final Answer:

    Create a factory function for each router that accepts the database client and returns a configured router -> Option B
  4. Quick Check:

    Factory functions for injection = Create a factory function for each router that accepts the database client and returns a configured router [OK]
Hint: Use factory functions to pass shared resources cleanly [OK]
Common Mistakes:
  • Using global variables which reduce testability
  • Attaching client to app instance instead of injecting
  • Initializing client on every request causing overhead
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard