惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
N
Netflix TechBlog - Medium
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
J
Java Code Geeks
V
Visual Studio Blog
H
Help Net Security
Engineering at Meta
Engineering at Meta
Hugging Face - Blog
Hugging Face - Blog
Microsoft Security Blog
Microsoft Security Blog
腾讯CDC
博客园 - 【当耐特】
B
Blog
Stack Overflow Blog
Stack Overflow Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
GbyAI
GbyAI
博客园 - 司徒正美
博客园 - 叶小钗
Y
Y Combinator Blog
MyScale Blog
MyScale Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
G
Google Developers Blog
酷 壳 – CoolShell
酷 壳 – CoolShell

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Part 1: Taming Asynchronous JavaScript: How to Build a "M...
krishnadaspc · 2026-05-23 · via DEV Community

Have you ever tried to catch water from a fire hydrant with a paper cup?

That is exactly what it feels like when you are building a JavaScript app and data starts coming in way faster than your code can process it. Maybe you are handling a flood of incoming webhooks, reading a massive file, or listening to a busy WebSocket.

If your data sender is faster than your data receiver, things break.

What you need is a waiting room. A place where incoming data can chill out until your app is ready to handle it. In computer science, this is called a "Queue" or a "Channel." Today, we are going to build one from scratch. Let's call it our Mailbox.

The Idea Behind the Mailbox
Think of a literal physical mailbox.

The Mail Carrier (The Producer): Drops letters into the box. They don't care if you are home; they just drop the mail and leave.

You (The Consumer): You check the mailbox. If there is mail, you take it. If the box is empty, you just wait until the mail carrier shows up.

We can recreate this exact relationship in JavaScript using Promises. Here is the code. It might look a little magical at first, but we will break it down right after!

export class Mailbox {
  constructor() {
    this.messages = []
    this.waiters = []
    this.closed = false
  }

  push(message) {
    if (this.closed) {
      throw new Error("Mailbox is closed")
    }

    // Deliver directly to waiting consumer
    if (this.waiters.length > 0) {
      const resolve = this.waiters.shift()
      resolve(message)
      return
    }

    this.messages.push(message)
  }

  async pop() {
    // Message already available
    if (this.messages.length > 0) {
      return this.messages.shift()
    }

    // Closed mailbox
    if (this.closed) {
      return null
    }

    // Wait for future message
    return new Promise((resolve) => {
      this.waiters.push(resolve)
    })
  }

  close() {
    this.closed = true

    // Wake all waiting consumers
    while (this.waiters.length > 0) {
      const resolve = this.waiters.shift()
      resolve(null)
    }
  }

  get size() {
    return this.messages.length
  }

  async *[Symbol.asyncIterator]() {
    while (true) {
      const msg = await this.pop()

      if (msg === null) {
        break
      }

      yield msg
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

The "Aha!" Moment: Pausing JavaScript

The coolest part of this code is inside the pop() method.

Usually, when we use a Promise in JavaScript, it's for something like fetch()

You make a request, and eventually, it resolves.

But here, we are doing something sneaky. If the mailbox is empty, we create a new Promise, but we take its resolve function and shove it into our this.waiters array. We are essentially bottling up the ability to finish the Promise for later.

Your code effectively pauses. It just sits there, waiting.

Then, when the push() method gets called, it looks inside this.waiters, pulls out that bottled-up resolve function, and triggers it with the new message. Boom! Your paused code instantly wakes up with the data.

How to Use It

Because we added that weird looking [Symbol.asyncIterator] at the bottom of the class, using our Mailbox is beautifully simple:

const mailbox = new Mailbox();

// 1. You: waiting for mail
async function readMail() {
  // This loop will naturally pause and wait for new messages!
  for await (const msg of mailbox) {
    console.log("Just got:", msg);
  }
  console.log("No more mail coming!");
}
readMail();

// 2. The Mail Carrier: dropping off mail at random times
mailbox.push("Letter 1");
setTimeout(() => mailbox.push("Letter 2"), 1000);
setTimeout(() => mailbox.close(), 2000);

Enter fullscreen mode Exit fullscreen mode

This setup works flawlessly for everyday tasks. But there is a hidden monster in this code.

If you get too popular—say, someone drops 1,000,000 letters into your mailbox at once—this exact code will completely freeze your server for minutes. In Part 2, we are going to find out exactly why JavaScript hates huge arrays, and how to fix our Mailbox to handle millions of messages in a fraction of a second.

The link to the repo of full source code of this: https://github.com/pckrishnadas88/mailbox