JavaScript ES6+ Free Crash Course 2025 – Key ES6+ Features – Modules & Promises

In this tutorial of this JavaScript ES6+ Crash course 2025 we are going to show you some brief introduction and code examples for usage of Modules and Promises in JavaScript. Previously we have discussed: Arrow Functions, Destructuring & Rest Operators and Classes and Inheritance.

ES6 modules in JavaScript provide a way to organize and share code between JavaScript files. Here is the code example:

/ math.js
export const PI = 3.14159;

export function square(x) { return x * x;
}

export default function cube(x) { return x * x * x;
}

// main.js
import cube, { PI, square } from './math.js';
console.log(PI); // 3.14159
onsole.log(square(4)); // 16
console.log(cube(3));	// 27

// Importing all exports as an object import * as math from './math.js';
console.log(math.PI);	// 3.14159
console.log(math.square(4)); // 16

Best Practices:

  • Use named exports for multiple functions/variables.
  • Use default export for the main functionality of a module. Keep modules focused on a single responsibility.

Common Pitfalls:

  • Circular dependencies can cause issues.
  • Browser support may require transpilation or bundling. Be cautious with side effects in modules.

Promises

Promises provide a way to handle asynchronous operations more elegantly than callbacks. Now let’s see how Promises work in JavaScript with code example.


function fetchData(url) {
return new Promise((resolve, reject) => {
// Simulating an API call setTimeout(() => {
if (url) {
resolve({ data: 'Success' });
} else {
reject('Error: Invalid URL');
}
}, 1000);
});
}

fetchData('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.error(error));

// Chaining promises
fetchData('https://api.example.com/user')
.then(user => fetchData(`https://api.example.com/posts/${user.id}`))
.then(posts => console.log(posts))
.catch(error => console.error(error));

// Promise.all Promise.all([
fetchData('https://api.example.com/users'), fetchData('https://api.example.com/posts')
])
.then(([users, posts]) => {
console.log('Users:', users); console.log('Posts:', posts);
})
.catch(error => console.error(error));

Best Takeaways 

  • Always handle potential errors using .catch().
  • Use Promise.all() for multiple independent asynchronous operations. Avoid deeply nested .then() chains; consider using async/await instead.

Common Pitfalls

  • Forgetting to return a value in .then() callbacks.
  • Not handling errors properly, leading to unhandled promise rejections. Creating “Promise hell” with excessive nesting.