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

推荐订阅源

L
Lohrmann on Cybersecurity
Martin Fowler
Martin Fowler
Engineering at Meta
Engineering at Meta
腾讯CDC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
TaoSecurity Blog
TaoSecurity Blog
博客园_首页
Vercel News
Vercel News
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
The Exploit Database - CXSecurity.com
量子位
Project Zero
Project Zero
A
Arctic Wolf
小众软件
小众软件
NISL@THU
NISL@THU
C
CERT Recently Published Vulnerability Notes
有赞技术团队
有赞技术团队
MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
News and Events Feed by Topic
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Troy Hunt's Blog
P
Privacy & Cybersecurity Law Blog
Security Latest
Security Latest
B
Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
Schneier on Security
Schneier on Security
The Hacker News
The Hacker News
K
Kaspersky official blog
C
Check Point Blog
Hacker News: Ask HN
Hacker News: Ask HN
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Webroot Blog
Webroot Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
人人都是产品经理
人人都是产品经理
AI
AI
Cisco Talos Blog
Cisco Talos Blog
MyScale Blog
MyScale Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
S
Schneier on Security
P
Palo Alto Networks Blog

Echo JS

Desktop apps Introducing mermaid-lint: Stop Shipping Broken Diagrams How We Cut Slow Responses by 80% Migrating to Next.js App Router GitHub - ant-design/ant-design-cli: Ant Design on your command line. Query component knowledge, analyze project usage, and guide migrations — fully offline. Uncovering the Magic Behind Playwright React Performance Isn’t About useMemo — It’s About Render Boundaries T2 No Escape Hatches · Prickles GitHub - auto-agent-protocol/auto-agent-protocol: Automotive Agent Protocol GitHub - coactionjs/coaction: Zustand-style state management with built-in render tracking and cached computed state GitHub - williamtroup/Rattribute.js: ❓ A lightweight JavaScript library for automatically changing HTML element attributes based on responsive screen sizes. GitHub - williamtroup/Rink.js: 🔗 A JavaScript library for generating responsive HTML link targets. SVAR Kanban: Interactive Task Board Component for Svelte, React, and Vue Performance Cost of Popular 3rd Party Scripts date-light - Tiny date utilities for JavaScript When React Hooks Stop Scaling: Moving Complex State to Zustand - Oren Farhi GitHub - jskits/loggerjs: A faster, more powerful isomorphic logger Out Loud — Free AI Text to Speech Pocket DB — Embedded single-file NoSQL for Node.js billboard.js 4.0 release: Canvas rendering mode, 94.3% faster! GitHub - thegruber/linkpeek: Secure TypeScript link preview and URL metadata extractor for Open Graph, Twitter Cards, JSON-LD, Node/Bun/Deno/edge. GitHub - evoluteur/healing-frequencies: Play the healing frequencies of various sets of tuning forks: Solfeggio, Organs, Mineral nutrients, Ohm, Chakras, Cosmic octave, Otto, DNA nucleotides... or custom. Animated sine waves - 27 lines of pure JavaScript Framework | Neutralinojs GitHub - AllThingsSmitty/typescript-tips-everyone-should-know: ✅ A curated collection of practical TypeScript patterns that improve safety, readability, maintainability, and developer experience. 🧠 Heat.js : JavaScript Heat Map GitHub - iDev-Games/State-JS: State.js is a CSS‑reactive framework that makes UI state and updates flow through CSS instead of JavaScript logic. GitHub - yankouskia/gameplate: :video_game: Boilerplate for creating game with WebGL & Redux :game_die: GitHub - yankouskia/get-browser: 💻 Lightweight tool to identify the browser (mobile+desktop detection)📱 GitHub - yankouskia/is-incognito-mode: Identify whether browser is in incognito mode 👀
The quiet problem with unnecessary async - Matt Smith
https://allthingssmitty.com/about/ · 2026-06-08 · via Echo JS

There’s a pattern in JavaScript codebases that quietly spreads complexity through entire applications. You’ve probably seen something like this:

async function getConfig() {
  return defaultConfig;
}

At first glance, this barely feels like a decision.

Maybe one day getConfig() will fetch something remotely. Maybe it’ll hit IndexedDB later. Making it async now can feel harmless, even responsible.

The problem is that async changes the contract of the function.

What changes when a function becomes async

The moment a function becomes async, it stops returning a value directly and starts returning a Promise, even if there’s no await inside.

That changes every caller downstream.

const config = getConfig();

becomes:

const config = await getConfig();

And once that happens, the surrounding code starts adapting, too:

  • Callers become async-aware
  • Tests become async-aware
  • Composition utilities start propagating Promises

People sometimes call this the function coloring problem:

Years ago I inherited a codebase where almost every helper returned a Promise. Tracing a request path meant following await after await before eventually discovering where the actual asynchronous work was happening. Most of those functions were just returning data that was already in memory.

What made it frustrating wasn’t the syntax itself. It was the uncertainty. Every function looked equally “asynchronous” from the outside, so the signatures stopped telling me where the real I/O lived.

That’s when I started paying more attention to where async boundaries actually belong.

“We might need it later”

A common justification looks like this:

async function getFeatureFlags() {
  return localFlags;
}

And the reasoning is usually:

Sometimes that’s a good reason.

Public libraries often expose async APIs early because changing them later can be painful. Consistency across implementations matters, too.

Application code tends to be different. Internal helpers often become async speculatively even when nothing asynchronous is happening yet.

Right now:

  • There’s no suspension point
  • No I/O
  • No asynchronous dependency

But every consumer still pays the async cost today.

async communicates meaning

When I’m skimming code I’m unfamiliar with, I use function signatures as shortcuts.

If I see this:

async function loadUser()

I assume there’s a real boundary there somewhere:

  • Network activity
  • Storage access
  • Background processing

Something that can’t be produced immediately.

That’s useful information. Function signatures help us build a mental model of a system. When a function returns synchronously available data, marking it async starts implying work that isn’t actually happening.

The mental overhead

Performance usually isn’t the issue here. Modern JavaScript engines handle Promises well. The cost is mostly cognitive.

Compare:

function getTheme() {
  return currentTheme;
}

with:

async function getTheme() {
  return currentTheme;
}

Now compare the call sites:

const theme = getTheme();
applyTheme(theme);

vs.:

const theme = await getTheme();
applyTheme(theme);

One stays inside synchronous control flow. The other introduces async flow, even though the underlying data is already available.

Tests often make this especially noticeable. One unnecessary Promise can turn a simple test file into a chain of async setup and assertions.

Async boundaries matter

Modern front-end systems are already heavily async:

  • Streaming SSR
  • React Server Components
  • Edge runtimes
  • Server actions
  • Async routing
  • Suspense-driven rendering

Async boundaries affect rendering behavior, composition, error handling, debugging, and the shape of an application. Because of that, I try to treat them as architectural decisions rather than implementation details.

A rough rule I follow: async should represent real async boundaries, not hypothetical future requirements. If a function doesn’t await anything, it’s worth asking why it’s async in the first place.

Keep APIs honest

Instead of designing around what a function might someday become, design around what it is today.

If it’s synchronous:

function getConfig() {
  return defaultConfig;
}

keep it synchronous.

If real asynchronous work arrives later, introduce async semantics deliberately. Until then, smaller async boundaries are easier to reason about, easier to trace, and make function signatures more meaningful.

Because async doesn’t just change a function implementation. It changes the shape of the code around it.

The biggest differences are:

  • Added a concrete personal anecdote early.
  • Removed some repeated “async propagates outward” explanations.
  • Replaced a few generalized statements (“people rely on function signatures”) with first-person observations (“when I’m skimming unfamiliar code…”).
  • Tightened the ending so it lands a little harder instead of re-explaining the thesis one more time.