📖 What You’ll Learn:
-
What
async/await
is and why it’s better than.then()/.catch()
-
How to properly validate user input using
express-validator
-
How to use Mongoose models to structure user data
-
How to return consistent error responses using
next()
andtry/catch
🧱 Final File Structure (Reminder):
src/
│
├── models/
│ └── User.ts
├── controllers/
│ └── UserController.ts
├── routes/
│ └── UserRouter.ts
├── validators/
│ └── UserValidator.ts
🧠 Understanding async/await
and try/catch
🔹 What is async/await
?
-
async
functions always return a Promise. -
await
is used insideasync
functions to wait for the Promise to resolve. -
It makes asynchronous code look like synchronous code.
🔹 Why use async/await
over .then().catch()
?
.then().catch() |
async/await + try/catch |
---|---|
Nested callbacks can get messy | Cleaner and more readable |
Error handling gets hard to trace | Centralized error handling with try/catch |
Harder to debug | Easier to debug and maintain |
✅ Final Updated Code with Explanation
🗂️ controllers/UserController.ts
import { validationResult } from ‘express-validator’; import User from ‘../models/User’; export class UserController { static async signUp(req, res, next) { // Validate incoming data const errors = validationResult(req); if (!errors.isEmpty()) { return next(new Error(errors.array()[0].msg)); } // Destructure request body const { email, password, username } = req.body; // Prepare data const userData = { email, password, username }; try { // Wait for Mongoose to save the user const user = await new User(userData).save(); // Send the saved user as response res.status(201).json(user); } catch (err) { // Pass error to error-handling middleware next(err); } } }
🔍 Detailed Explanation for Beginners
Line | Explanation |
---|---|
async signUp(req, ...) |
Makes the function return a Promise so we can use await inside it |
validationResult(req) |
Gathers validation errors from express-validator |
if (!errors.isEmpty()) |
If there are validation errors, we send the first error back using next() |
await new User(data).save() |
Saves the user to MongoDB, but waits until it’s actually completed |
try { ... } catch (e) |
Catches any errors (like DB issues) and forwards them to error middleware |
📬 Testing in Postman
-
URL:
http://localhost:5000/api/user/signup
-
Method:
POST
-
Body Type:
x-www-form-urlencoded
Key | Value |
---|---|
[email protected] | |
password | testPassword123 |
username | testuser |
✅ Sample Success Response
{ “_id”: “684edfa123abc671f7dfcc11”, “email”: “[email protected]”, “username”: “testuser”, “password”: “testPassword123”, “created_at”: “2025-06-28T12:00:00Z”, “updated_at”: “2025-06-28T12:00:00Z”, “__v”: 0 }
❌ Sample Error Responses
🔸 Missing Field
{ “message”: “Email is Required”, “status_code”: 500 }
🔸 Duplicate Email
{ “message”: “User Already Exist”, “status_code”: 500 }
🧠 Key Takeaways
-
Always validate incoming data using a middleware (like
express-validator
). -
Use
async/await
+try/catch
for cleaner, more readable code. -
Use
next()
to forward errors to a centralized error handler. -
Structure your project using MVC pattern: Models, Routes, Controllers, Validators.