JavaScript Fundamentals Every Beginner Should Master
Variables, functions, arrays, objects, and the DOM — the plain JavaScript every framework is built on top of.
Callback hell was the original way JavaScript handled anything asynchronous, and it was miserable. Promises fixed the structure; async/await made them read like normal code. Here's how to actually reason about both.
A Promise represents a value that doesn't exist yet, but will — either successfully (resolved) or with an error (rejected). Every fetch() call returns one:
fetch('/api/posts')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error('Failed:', err));
async function loadPosts() {
try {
const res = await fetch('/api/posts');
const data = await res.json();
console.log(data);
} catch (err) {
console.error('Failed:', err);
}
}
Under the hood this compiles to the exact same Promise chain — await is just syntax that pauses the function until the Promise settles, without blocking the rest of the browser.
A very common beginner mistake — awaiting one request, then the next, when neither depends on the other:
// Slow: waits for posts before even starting the users request
const posts = await getPosts();
const users = await getUsers();
// Fast: both start immediately
const [posts, users] = await Promise.all([getPosts(), getUsers()]);
A rejected Promise inside an async function without a try/catch becomes an unhandled rejection — silently breaking your app in ways that are hard to debug. Always wrap awaited calls that can fail (which is: any network call, ever) in try/catch.
const results = await Promise.allSettled([getUserA(), getUserB(), getUserC()]);
// results: array of { status: 'fulfilled', value } or { status: 'rejected', reason }
Unlike Promise.all, this doesn't reject the whole batch if one request fails — useful when you want partial results rather than an all-or-nothing outcome.
Once async/await clicks, most of what looked like "advanced JavaScript" in framework tutorials (data fetching in React useEffect, Next.js Server Components) turns out to just be this same pattern applied in a specific place.
Variables, functions, arrays, objects, and the DOM — the plain JavaScript every framework is built on top of.
Template literals, destructuring, optional chaining, and modules — the JavaScript you actually see in every modern codebase.
A practical walkthrough of useState, useEffect, useRef, and useContext — the hooks that cover the majority of real React component logic.