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

推荐订阅源

B
Blog RSS Feed
Jina AI
Jina AI
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
Hugging Face - Blog
Hugging Face - Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
博客园 - 司徒正美
罗磊的独立博客
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
WordPress大学
WordPress大学
Vercel News
Vercel News
A
About on SuperTechFans
I
InfoQ
D
DataBreaches.Net
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享
P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
美团技术团队

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
✋Await!! Aren't you hindering concurrency?
KrishnenduDG · 2026-04-27 · via DEV Community

Well, more often than not while building stuff with JS/TS, we tend to use await whenever we come across an API call (or something which goes out of the synchronous flow of the main thread execution). That takes away the concerns of handling all the asynchronicity that the language offers — and NGL, it’s the easiest way out. No callbacks (hence no chances of a callback hell), .then() syntax. Our code executes line-by-line, just as would have happened if the language followed a fully synchronous paradigm.

// Simulates an async function
async function foo() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("foo");
    }, 300);
  });
}

(async () => {
  const res = await foo();
  console.log(res);
})();

Enter fullscreen mode Exit fullscreen mode

💻 Guess the output of the code snippet.
It's foo.
Straightforward, isn't it?

Now, take two scenarios where multiple async calls are being handled in a single function.

But before that, let's prepare the stage for the whole demonstration.

Let's create a fake DB using JS objects.

// Consider it as a fake DB
const users = [
  { id: 1, name: "Krishnendu", age:23 },
  { id: 2, name: "Rohan", age:25 },
];
const posts = [
  { id: 101, userId: 1, title: "Hello World" },
  { id: 102, userId: 1, title: "Another Hello World" },
  { id: 103, userId: 2, title: "Just for posting" },
];

Enter fullscreen mode Exit fullscreen mode

Consider these utility functions, which are async in nature and would be useful to fetch the various details of user, posts and jokes.

// Simulating a fake DB call for fetching a user
const getUser = (id) =>
  new Promise((resolve) => {
    setTimeout(() => resolve(users.find((u) => u.id === id)), 300);
  });

Enter fullscreen mode Exit fullscreen mode

// Simulating a fake DB call for fetching user posts
const getPosts = (userId) =>
  new Promise((resolve) => {
    setTimeout(() => resolve(posts.filter((p) => p.userId === userId)), 300);
  });

Enter fullscreen mode Exit fullscreen mode

// API call for generating jokes
const generateJoke = async () => {
  const res = await fetch(
    "https://official-joke-api.appspot.com/random_joke"
  );
  return res.json();
};

Enter fullscreen mode Exit fullscreen mode

Scenario - 1

(async () => {
  try {
    // Fetching the User
    const user = await getUser(1);

    // If user not found, then we just stop the further execution
    if (!user) {
      throw new Error("User not found");
    }

    // User found, so find posts
    const userPosts = await getPosts(user.id);

    console.log(user);
    console.log(userPosts);
  } catch (err) {
    console.error("Error:", err.message);
  }
})();

Enter fullscreen mode Exit fullscreen mode

In the above code snippet, two asynchronous calls have been handled in the most conventional way. First we wait for the getUser call to finish, then we hop on to the getPosts call.

Scenario - 2

(async () => {
  let userDetails = null;

  try {
    // fetch user
    userDetails = await getUser(1);
  } catch (error) {
    console.log("User fetch failed");
  }

  // fetch joke
  const joke = await generateJoke();

  // output
  if (userDetails) {
    console.log(
      `User: ${userDetails.name}, Age: ${userDetails.age}`
    );
  } else {
    console.log("No User found");
  }

  console.log(`Joke: ${joke.setup} ${joke.punchline}`);
})();

Enter fullscreen mode Exit fullscreen mode

Similarly here, we wait for the completion of getUser call only to jump on the next generateJoke call.

Now if we analyse carefully, for Scenario-1, it does make sense to wait for the first call of user fetching and then move on to the next call of finding the corresponding posts. Those are Interdependent calls. But for Scenario-2, both the calls are not even related to each other, let alone their dependence. So aren't we killing the computational time while waiting for the first call of fetching user details? 🤔

And there comes the actual scope for leveraging concurrency in your code. What if, instead of waiting for the previous call to finish, we start both (or multiple) calls at the same time, let them execute CONCURRENTLY and in the end we wait for the accumulated result?

Promise.all()

Good news is that JavaScript (and also TypeScript) inherently addresses the above concern and exposes a way of handling multiple asynchronous calls, without letting go of the concurrent behaviour.

Promise.all() takes in a collection (or more formally in JS/TS, an array) of promises and itself returns a Promise.

Promise.all() preserves the order of the input promises, so the resolved values are returned in the same order, making the result array easy to index.

Below code snippet demonstrates the same.

(async () => {
  // Takes in an array of promises and returns a promise
  const resultantPromise = Promise.all([getUser(1), generateJoke()]);

  // Promise.all() preserves the order of async calls, so its very easy to extract the results
  const [userDetails, jokeFetched] = await resultantPromise;

  if (userDetails) {
    console.log(
      `User's name is ${userDetails.name} and age is ${userDetails.age}`,
    );
  } else {
    console.log("No User found");
  }
  console.log(`Joke fetched: ${jokeFetched.setup} ${jokeFetched.punchline}`);
})();

Enter fullscreen mode Exit fullscreen mode

Promise.allSettled()

But why? Promise.all() lets us handle all the async calls efficiently and concurrently. Then why this new method?

Yes, that's true but there's a big caveat with Promise.all(). If any of the async calls fail, the resultant promise inherently gets rejected. Now, that's not an ideal situation for all use cases.

There comes Promise.allSettled(). Similar to Promise.all() in usage, but very different in behavior, it doesn’t fail just because one of the promises fails. Instead the resultant Promise always resolves and returns an array of result objects. It waits for all promises to settle (either fulfilled or rejected) before returning the results.

Array of objects? 🤔
Yes. Each element in the array contains the status of the async call and the corresponding value (if the async call succeeds) or reason (if the call fails).

Below code snippet makes it a bit clear.

(async () => {
  // Promise.allSettled() preserves the order of async calls, so its very easy to extract the results
  const [userResult, jokeResult] = await Promise.allSettled([
    getUser(1),
    generateJoke(),
  ]);

  // If the promise is resolved then the "status" is always "fulfilled" else it is always "rejected"
  if (userResult.status === "fulfilled") {
    const userDetails = userResult.value;
    console.log(
      `User's name is ${userDetails.name} and age is ${userDetails.age}`,
    );
  } else {
    console.log("No User found");
  }

  // Similarly, for the joke API call, we can explicitly handle both "resolve" and "reject"
  if (jokeResult.status === "fulfilled") {
    const jokeFetched = jokeResult.value;
    console.log(`Joke fetched: ${jokeFetched.setup} ${jokeFetched.punchline}`);
  } else {
    console.log("Joke fetching failure");
  }
})();

Enter fullscreen mode Exit fullscreen mode

Here, even if the getUser() call fails, we still can hope the generateJoke() to succeed.

Clearly, we have explicit control over each async call and its corresponding outcome and each outcome is independent of the others.

Choosing the right method

Honestly, there can be three common scenarios while dealing with multiple async calls and each can be handled with a specific method.

  • When your calls are dependent on each other, use the conventional await methodology. Handle them sequentially, since later computations depend on earlier results.

  • When the calls are independent of each other, there are two common scenarios:

    • Stop the computation if any one fails → use Promise.all().
    • Wait for all the calls to finish, regardless of the other calls' outcomes → use Promise.allSettled().

Other use cases might involve Promise.any() or Promise.race(), but that's a story for another day.

Conclusion

Well, JS/TS provides a variety of options to handle concurrency and each of them was designed with a specific use case in mind.

Use them wisely! 😎
Don’t just write async code — understand it. 👋