<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bishal Singh</title>
    <description>The latest articles on DEV Community by Bishal Singh (@bishal_singh_51754b00bee0).</description>
    <link>https://dev.to/bishal_singh_51754b00bee0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3948903%2F808eb165-a526-4f76-9fba-73544c2f2fdb.png</url>
      <title>DEV Community: Bishal Singh</title>
      <link>https://dev.to/bishal_singh_51754b00bee0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bishal_singh_51754b00bee0"/>
    <language>en</language>
    <item>
      <title>I Built My First Backend API in One Evening — Here's</title>
      <dc:creator>Bishal Singh</dc:creator>
      <pubDate>Fri, 29 May 2026 12:43:23 +0000</pubDate>
      <link>https://dev.to/bishal_singh_51754b00bee0/i-built-my-first-backend-api-in-one-evening-heres-4alh</link>
      <guid>https://dev.to/bishal_singh_51754b00bee0/i-built-my-first-backend-api-in-one-evening-heres-4alh</guid>
      <description>&lt;p&gt;__I am learning to code. My tutor taught me how to create an HTTP server using Express, and the same evening he gave me a task — build a basic TODO app using that knowledge.&lt;br&gt;
My first thought was — "Is that even possible with this little knowledge?"&lt;br&gt;
The answer, as it turns out, is yes. Completely yes.&lt;br&gt;
Here is everything I learned, explained the way I wish someone had explained it to me.&lt;/p&gt;

&lt;p&gt;First, What Even Is a Backend?&lt;br&gt;
Before I wrote a single line of code, I had to understand what a backend actually does.&lt;br&gt;
Think about a restaurant.&lt;br&gt;
You sit down. A waiter comes. You say — "Get me a burger." The waiter goes to the kitchen, gets it, and brings it back.&lt;br&gt;
Now map that to the internet —&lt;/p&gt;

&lt;p&gt;You are the browser&lt;br&gt;
The waiter is Express&lt;br&gt;
The kitchen is your backend logic&lt;br&gt;
The burger is the data&lt;/p&gt;

&lt;p&gt;When you type a URL in your browser and hit enter, you are placing an order. The server's job is to take that order, do something, and bring back a response.&lt;br&gt;
That's it. That's the entire internet in one analogy.&lt;/p&gt;

&lt;p&gt;req and res — What Do They Actually Mean?&lt;br&gt;
When I first saw req in Express code, I thought it meant require. It doesn't. That was my first mistake.&lt;br&gt;
Here's what they actually mean —&lt;br&gt;
req (request) — everything the client sends TO the server. Like when you place a food order with all your details — extra cheese, no onions, table number 5. That whole thing is the request.&lt;br&gt;
res (response) — what the server sends BACK to the client. The food, or maybe "sorry, that's not available."&lt;br&gt;
A simple test — if someone fills a login form with their email and password and hits submit, which one carries that data to the server?&lt;br&gt;
req. Because the user is sending data to the server.&lt;/p&gt;

&lt;p&gt;HTTP Methods — The Types of Requests&lt;br&gt;
Not all requests are the same. When a client talks to a server, it has to say what type of request it is making. These are called HTTP Methods.&lt;br&gt;
MethodReal Life MeaningGETI want to read or fetch somethingPOSTI want to create or send something newPATCHI want to update something partiallyDELETEI want to delete something&lt;br&gt;
When you type a URL in your browser and hit enter, your browser is automatically making a GET request — because you just want to see something.&lt;br&gt;
And yes — when you add a new todo, that's a POST — because you are sending new data to the server.&lt;/p&gt;

&lt;p&gt;Designing the API Before Writing Code&lt;br&gt;
Here is something I did not expect — you can design your entire backend before writing a single line of code.&lt;br&gt;
A TODO app needs four operations. One for each letter of CRUD — Create, Read, Update, Delete.&lt;br&gt;
GET    /todos        →  fetch all todos&lt;br&gt;
POST   /todos        →  add a new todo&lt;br&gt;
PATCH  /todos/:id    →  mark a todo done or undone&lt;br&gt;
DELETE /todos/:id    →  remove a todo&lt;br&gt;
See that :id in the last two? That's a dynamic part of the URL. It means the client tells the server which specific todo to update or delete, right in the URL itself — like /todos/3 to target the todo with id 3.&lt;/p&gt;

&lt;p&gt;req.body vs req.params&lt;br&gt;
When the server receives a request, it needs to read the data the client sent. There are two main places data can live —&lt;br&gt;
req.body — data the client sends privately inside the request. Like a form submission. You cannot see it in the URL.&lt;br&gt;
req.params — data that is visible in the URL itself. Like /todos/3 — that 3 is a param. You read it as req.params.id.&lt;br&gt;
A simple way to remember it —&lt;br&gt;
Where is the data?req.bodyHidden inside the requestreq.paramsVisible in the URL&lt;br&gt;
So for each route in our TODO app —&lt;br&gt;
RouteUsesGET /todosNothing — just send back all todosPOST /todosreq.body — to get the todo textPATCH /todos/:idreq.params — to know which todoDELETE /todos/:idreq.params — to know which todo&lt;/p&gt;

&lt;p&gt;The Code — Every Line Explained&lt;br&gt;
Setup&lt;br&gt;
javascriptconst express = require('express')&lt;br&gt;
const app = express()&lt;br&gt;
const port = 3000&lt;br&gt;
app.use(express.json())&lt;/p&gt;

&lt;p&gt;let todos = []&lt;/p&gt;

&lt;p&gt;require('express') — import the Express library&lt;br&gt;
express() — create the actual app object&lt;br&gt;
express.json() — this is important. When the client sends data, it arrives as raw text. This line converts it into a proper JavaScript object so req.body actually works. Without it, req.body would be undefined.&lt;br&gt;
let todos = [] — our in-memory "database". Just a plain array. Data resets when the server restarts, but that's fine for a basic app.&lt;/p&gt;

&lt;p&gt;GET — Fetch All Todos&lt;br&gt;
javascriptapp.get('/todos', function(req, res) {&lt;br&gt;
  res.json(todos)&lt;br&gt;
})&lt;br&gt;
When someone hits GET /todos, send back the entire todos array. No input needed. Simple.&lt;/p&gt;

&lt;p&gt;POST — Add a New Todo&lt;br&gt;
javascriptapp.post('/todos', function(req, res) {&lt;br&gt;
  const text = req.body.text&lt;br&gt;
  const newTodo = {&lt;br&gt;
    id: todos.length + 1,&lt;br&gt;
    text: text,&lt;br&gt;
    done: false&lt;br&gt;
  }&lt;br&gt;
  todos.push(newTodo)&lt;br&gt;
  res.json(newTodo)&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;req.body.text — grab the text the user typed from the request body&lt;br&gt;
id: todos.length + 1 — dynamic id. If 0 todos exist, id is 1. If 1 exists, id is 2. And so on.&lt;br&gt;
done: false — every new todo starts as not completed&lt;br&gt;
todos.push(newTodo) — add it to the array&lt;br&gt;
res.json(newTodo) — send back the created todo&lt;/p&gt;

&lt;p&gt;DELETE — Remove a Todo&lt;br&gt;
javascriptapp.delete('/todos/:id', function(req, res) {&lt;br&gt;
  const id = Number(req.params.id)&lt;br&gt;
  const index = todos.findIndex(function(todo) {&lt;br&gt;
    return todo.id === id&lt;br&gt;
  })&lt;br&gt;
  todos.splice(index, 1)&lt;br&gt;
  res.json({ message: "Deleted Successfully" })&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;Number(req.params.id) — req.params always gives a string. But our todo ids are numbers. So "1" === 1 is false in JavaScript — the todo would never be found. Number() converts it properly.&lt;br&gt;
findIndex — goes through the array and returns the position of the matching todo (like 0, 1, 2)&lt;br&gt;
splice(index, 1) — removes 1 item at that position&lt;/p&gt;

&lt;p&gt;PATCH — Mark Done or Undone&lt;br&gt;
javascriptapp.patch('/todos/:id', function(req, res) {&lt;br&gt;
  const id = Number(req.params.id)&lt;br&gt;
  const todo = todos.find(function(todo) {&lt;br&gt;
    return todo.id === id&lt;br&gt;
  })&lt;br&gt;
  todo.done = !todo.done&lt;br&gt;
  res.json(todo)&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;todos.find — unlike findIndex, this returns the actual todo object, not its position&lt;br&gt;
!todo.done — the ! means "opposite of". So false becomes true and true becomes false. One line to flip the status.&lt;/p&gt;

&lt;p&gt;Starting the Server&lt;br&gt;
javascriptapp.listen(port, function() {&lt;br&gt;
  console.log(&lt;code&gt;Example app listening on port ${port}&lt;/code&gt;)&lt;br&gt;
})&lt;br&gt;
This starts the server on port 3000. Your app is now running at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;find vs findIndex — What's the Difference?&lt;br&gt;
This confused me at first, so let me explain it clearly.&lt;br&gt;
Imagine your todos array as a row of boxes —&lt;br&gt;
Position:  0                    1                   2&lt;br&gt;
           { id:1, text:"..." } { id:2, text:"..." } { id:3, text:"..." }&lt;br&gt;
find — goes through each box and returns the actual box that matches. You get the object itself.&lt;br&gt;
findIndex — goes through each box and returns the position number of the matching box (0, 1, 2...).&lt;br&gt;
Use find when you want to read or update the object. Use findIndex when you want to remove it with splice — because splice needs to know where to cut.&lt;/p&gt;

&lt;p&gt;A Mistake I Made — And Why It Matters&lt;br&gt;
The most frustrating bug I hit was this — my PATCH and DELETE routes were returning errors even though my code looked correct.&lt;br&gt;
The fix was one small thing —&lt;br&gt;
javascript// Wrong — id is a string "1"&lt;br&gt;
const id = req.params.id&lt;/p&gt;

&lt;p&gt;// Correct — id is now a number 1&lt;br&gt;
const id = Number(req.params.id)&lt;br&gt;
req.params always gives you a string. But todo ids in our array are numbers. So comparing "1" === 1 always returns false — the todo is never found, and the server crashes.&lt;br&gt;
Always convert req.params.id with Number() when comparing with numeric ids.&lt;/p&gt;

&lt;p&gt;Testing With Postman&lt;br&gt;
Once your server is running with node server.js, you cannot test POST, DELETE, or PATCH from a browser — the browser only makes GET requests when you type a URL.&lt;br&gt;
That's where Postman comes in. It lets you make any type of HTTP request and see the response.&lt;br&gt;
Here's what each test looks like —&lt;br&gt;
GET — method: GET, url: &lt;a href="http://localhost:3000/todos" rel="noopener noreferrer"&gt;http://localhost:3000/todos&lt;/a&gt; → returns [] initially&lt;br&gt;
POST — method: POST, url: &lt;a href="http://localhost:3000/todos" rel="noopener noreferrer"&gt;http://localhost:3000/todos&lt;/a&gt;, body (raw JSON): { "text": "Buy groceries" } → returns the created todo&lt;br&gt;
DELETE — method: DELETE, url: &lt;a href="http://localhost:3000/todos/1" rel="noopener noreferrer"&gt;http://localhost:3000/todos/1&lt;/a&gt; → returns { "message": "Deleted Successfully" }&lt;br&gt;
PATCH — method: PATCH, url: &lt;a href="http://localhost:3000/todos/1" rel="noopener noreferrer"&gt;http://localhost:3000/todos/1&lt;/a&gt; → returns the todo with done flipped to true&lt;/p&gt;

&lt;p&gt;The Pattern Behind Every Route&lt;br&gt;
After writing all four routes, I noticed something. Every single route follows the exact same pattern —&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the input     →  req.body or req.params&lt;/li&gt;
&lt;li&gt;Do something      →  read, create, update, or delete from the array&lt;/li&gt;
&lt;li&gt;Send a response   →  res.json()
That's it. Every backend route you will ever write follows this pattern. Just with different logic in the middle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What I'm Learning Next&lt;br&gt;
This basic app has one big limitation — every time the server restarts, all the data is gone. That's because we're storing todos in a plain JavaScript array in memory.&lt;br&gt;
The next steps are —&lt;/p&gt;

&lt;p&gt;Nodemon — automatically restarts the server when you save a file, so you don't have to do it manually every time&lt;br&gt;
A real database — like MongoDB, so todos persist even after restarting&lt;br&gt;
A frontend — connecting this backend to an actual HTML page so real users can interact with it&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;br&gt;
When my tutor assigned this, I genuinely didn't know if I could do it. I didn't even know what req meant a few hours earlier.&lt;br&gt;
But breaking it down step by step — the restaurant analogy, understanding req and res, designing the routes before coding, writing one route at a time — made it completely approachable.&lt;br&gt;
If you're a beginner reading this, the biggest thing I'd tell you is this — don't try to understand everything at once. Understand one concept, then the next. The code will start making sense faster than you think.&lt;br&gt;
The whole backend is just 40 lines of code. But understanding why every line is there? That's the real learning.&lt;/p&gt;

&lt;p&gt;Written by a beginner, for beginners. Still learning — one route at a time.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>backenddevelopment</category>
      <category>apiroutes</category>
    </item>
    <item>
      <title>async/await Finally Made Sense When I Stopped Treating It as Something New</title>
      <dc:creator>Bishal Singh</dc:creator>
      <pubDate>Tue, 26 May 2026 07:36:37 +0000</pubDate>
      <link>https://dev.to/bishal_singh_51754b00bee0/asyncawait-finally-made-sense-when-i-stopped-treating-it-as-something-new-gpj</link>
      <guid>https://dev.to/bishal_singh_51754b00bee0/asyncawait-finally-made-sense-when-i-stopped-treating-it-as-something-new-gpj</guid>
      <description>&lt;p&gt;&lt;em&gt;It is not a replacement for promises. It is just promises wearing a cleaner outfit. Here is how that clicked for me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8700fnfoa6r869jtdrx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8700fnfoa6r869jtdrx.png" alt=" " width="736" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have already understood promises — what they are, why they exist, and how errors travel through a chain — then async/await is genuinely one step away. Not a big step. One small step.&lt;/p&gt;

&lt;p&gt;The problem is most explanations treat it like an entirely new concept. It is not. Once I understood that, everything fell into place.&lt;/p&gt;

&lt;p&gt;What promises already solved&lt;br&gt;
Before getting into async/await, it helps to remember what promises fixed. Callbacks nested badly and errors stayed isolated — each function had no idea when something else in the chain failed. Promises fixed both of those things.&lt;/p&gt;

&lt;p&gt;But promises still had their own friction. Every step needed a .then. Reading a chain of five operations still required some mental effort to follow. It worked, but it did not feel natural.&lt;/p&gt;

&lt;p&gt;async/await did not come to fix a broken system. It came to make an already good system easier to read.&lt;/p&gt;

&lt;p&gt;Two keywords. One job each.&lt;br&gt;
async does one thing — it marks a function as one that contains waiting inside it. And it makes that function always return a promise, even if you return a plain value.&lt;/p&gt;

&lt;p&gt;await does one thing — it pauses that line, waits for the promise to resolve, and hands you the actual value directly. Then moves to the next line.&lt;/p&gt;

&lt;p&gt;That is the entire feature. Two keywords, two jobs.&lt;/p&gt;

&lt;p&gt;The moment it clicks&lt;br&gt;
Look at these two blocks of code. They do the exact same thing.&lt;/p&gt;

&lt;p&gt;promises&lt;br&gt;
fetchUser()&lt;br&gt;
  .then(user =&amp;gt; fetchPosts(user))&lt;br&gt;
  .then(posts =&amp;gt; fetchComments(posts))&lt;br&gt;
  .catch(err =&amp;gt; handleError(err))&lt;br&gt;
async/await&lt;br&gt;
async function getData() {&lt;br&gt;
  try {&lt;br&gt;
    const user = await fetchUser()&lt;br&gt;
    const posts = await fetchPosts(user)&lt;br&gt;
    const comments = await fetchComments(posts)&lt;br&gt;
  } catch(err) {&lt;br&gt;
    handleError(err)&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
Same logic. Same behavior. Same error handling. The second one just reads like normal top to bottom code. No chaining, no callbacks, no mental gymnastics.&lt;/p&gt;

&lt;p&gt;JavaScript is converting your async/await into promises behind the scenes anyway. You are not writing something different. You are writing something cleaner.&lt;/p&gt;

&lt;p&gt;A question I had about async functions&lt;br&gt;
When I first saw this:&lt;/p&gt;

&lt;p&gt;example&lt;br&gt;
async function greet() {&lt;br&gt;
  return "hello"&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;greet().then(val =&amp;gt; console.log(val)) // "hello"&lt;br&gt;
My first question was — does console.log actually print "hello" here? Yes it does. The async keyword secretly wraps your returned value in a resolved promise. The .then just unwraps it and gives you the value back.&lt;/p&gt;

&lt;p&gt;In real code you would never write it that way. You would just use await inside another async function to get the value cleanly. But that example showed me something important — async functions always return a promise, even when it does not look like they do.&lt;/p&gt;

&lt;p&gt;Error handling is just try/catch&lt;br&gt;
With promises you used .catch at the end of a chain. With async/await you use the same try/catch you already know from regular JavaScript.&lt;/p&gt;

&lt;p&gt;error handling&lt;br&gt;
async function getData() {&lt;br&gt;
  try {&lt;br&gt;
    const user = await fetchUser()&lt;br&gt;
    const posts = await fetchPosts(user)&lt;br&gt;
  } catch(err) {&lt;br&gt;
    console.log(err)  // catches anything that fails&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
Same behavior as .catch on a promise chain. If anything inside the try block fails, the error travels straight to catch. Nothing isolated, nothing silent.&lt;/p&gt;

&lt;p&gt;The one performance mistake worth knowing early&lt;br&gt;
Because await pauses execution, it is easy to accidentally write slow code without realizing it.&lt;/p&gt;

&lt;p&gt;slow — runs one by one&lt;br&gt;
const user = await fetchUser()&lt;br&gt;
const posts = await fetchPosts()&lt;br&gt;
const photos = await fetchPhotos()&lt;br&gt;
If these three do not depend on each other, you are making them wait in a queue for no reason. The fix is Promise.all — it runs all of them at the same time and waits for all of them together.&lt;/p&gt;

&lt;p&gt;fast — runs all at once&lt;br&gt;
const [user, posts, photos] = await Promise.all([&lt;br&gt;
  fetchUser(),&lt;br&gt;
  fetchPosts(),&lt;br&gt;
  fetchPhotos()&lt;br&gt;
])&lt;br&gt;
Same result. Much faster. This is the one thing worth keeping in the back of your mind as you start building real projects.&lt;/p&gt;

&lt;p&gt;The one line summary&lt;br&gt;
async/await is just promises, written so it reads like normal top to bottom code. Nothing new underneath. No new mental model required. If promises made sense, this is just the cleaner version of the same thing.&lt;/p&gt;

&lt;p&gt;The syntax will become muscle memory as you build things. What matters now is knowing you are not learning something entirely new — you are just learning a better way to write something you already understand.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
      <category>software</category>
    </item>
    <item>
      <title>I Finally Understood Callbacks and Promises. Here is What Actually Clicked.</title>
      <dc:creator>Bishal Singh</dc:creator>
      <pubDate>Sun, 24 May 2026 10:24:41 +0000</pubDate>
      <link>https://dev.to/bishal_singh_51754b00bee0/i-finally-understood-callbacks-and-promises-here-is-what-actually-clicked-4m86</link>
      <guid>https://dev.to/bishal_singh_51754b00bee0/i-finally-understood-callbacks-and-promises-here-is-what-actually-clicked-4m86</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqzuo70vseg7n278f18o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqzuo70vseg7n278f18o.jpg" alt=" " width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had read about callbacks and promises multiple times. I understood the words. But I kept feeling like I was missing something underneath — like everyone else had a mental model I did not have yet.&lt;/p&gt;

&lt;p&gt;Then two things clicked, and everything made sense. This post is about those two things.&lt;/p&gt;

&lt;p&gt;First: both are async. That is not the difference.&lt;br&gt;
When I first compared callbacks and promises, I thought the problem with callbacks was timing — that functions were somehow "not ready" when they needed to be. That was wrong.&lt;/p&gt;

&lt;p&gt;Both callbacks and promises handle timing just fine. That is literally what async code is for. The problem with callbacks has nothing to do with when things run. It is about what happens when things go wrong — and how readable your code stays as it grows.&lt;/p&gt;

&lt;p&gt;The waiter analogy that actually made sense&lt;br&gt;
Think about ordering food at a restaurant.&lt;/p&gt;

&lt;p&gt;With callbacks, you hand the waiter a note with instructions: "when the food is ready, bring it to table 4, then refill the water, then bring the bill." You have handed over control. The waiter runs your instructions. You are just waiting.&lt;/p&gt;

&lt;p&gt;With promises, the waiter gives you a buzzer and walks away. When it goes off, you decide what to do next. You are the one in control.&lt;/p&gt;

&lt;p&gt;Callbacks hand control away. Promises hand it back to you. That is the real difference.&lt;/p&gt;

&lt;p&gt;Problem one: nesting&lt;br&gt;
When you need multiple async operations in sequence, callbacks nest inside each other. Every new step lives inside the previous one.&lt;/p&gt;

&lt;p&gt;callback hell&lt;br&gt;
&lt;code&gt;fetchUser(function(user) {&lt;br&gt;
  fetchPosts(user, function(posts) {&lt;br&gt;
    fetchComments(posts, function(comments) {&lt;br&gt;
      // your actual logic is buried here&lt;br&gt;
    })&lt;br&gt;
  })&lt;br&gt;
})&lt;/code&gt; &lt;br&gt;
This is not just ugly. It is genuinely hard to debug. You cannot easily see the flow, and changing one step risks breaking the ones around it.&lt;/p&gt;

&lt;p&gt;Promises flatten this completely:&lt;/p&gt;

&lt;p&gt;promises&lt;br&gt;
fetchUser()&lt;br&gt;
  .then(user =&amp;gt; fetchPosts(user))&lt;br&gt;
  .then(posts =&amp;gt; fetchComments(posts))&lt;br&gt;
  .catch(err =&amp;gt; handleError(err))&lt;br&gt;
Same logic. Flat, readable, easy to follow from top to bottom.&lt;/p&gt;

&lt;p&gt;Problem two: functions do not know when others fail&lt;br&gt;
This was the one I almost missed — and it is arguably more important than the nesting issue.&lt;/p&gt;

&lt;p&gt;In a callback chain, each function is isolated. It only knows about itself. So if something breaks in the middle, the functions around it have no idea. The error does not travel. It just disappears silently unless you manually handle it at every single level.&lt;/p&gt;

&lt;p&gt;silent failure&lt;br&gt;
fetchUser(function(user) {&lt;br&gt;
  fetchPosts(user, function(posts) {  // fails here&lt;br&gt;
    fetchComments(posts, function() { // never runs&lt;br&gt;
      // nobody knows what went wrong&lt;br&gt;
    })&lt;br&gt;
  })&lt;br&gt;
})&lt;br&gt;
With promises, a failure anywhere in the chain automatically travels down to the nearest .catch. You do not have to do anything extra. One handler covers everything.&lt;/p&gt;

&lt;p&gt;error travels automatically&lt;br&gt;
fetchUser()&lt;br&gt;
  .then(user =&amp;gt; fetchPosts(user))   // fails here&lt;br&gt;
  .then(posts =&amp;gt; fetchComments())   // skipped&lt;br&gt;
  .catch(err =&amp;gt; handleError(err))   // caught here, automatically&lt;br&gt;
With callbacks, one forgotten error handler means a silent failure. With promises, errors bubble down on their own.&lt;/p&gt;

&lt;p&gt;So to summarize what actually changed&lt;br&gt;
Promises were not invented to replace callbacks for style reasons. They were invented because two specific things were genuinely painful:&lt;/p&gt;

&lt;p&gt;One — deeply nested callbacks made code hard to read and maintain as projects grew. Two — errors in a callback chain were isolated, invisible, and easy to miss entirely.&lt;/p&gt;

&lt;p&gt;Promises fix both. The chain stays flat, and failures propagate automatically.&lt;/p&gt;

&lt;p&gt;The syntax will become second nature as you build things. What matters first is understanding why promises exist at all — because once that is clear, the rest starts making sense on its own.&lt;/p&gt;

&lt;p&gt;Written by someone who just figured this out, for anyone else who is still figuring it out.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>development</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
