JavaScript
December 28, 2023
14 min read

Modern JavaScript Patterns for Better Code

Explore advanced JavaScript patterns and techniques that will make your code more maintainable and efficient.

#javascript
#patterns
#async
#functional-programming
#performance
Sanyam Jain
Full-Stack Developer
Modern JavaScript Patterns for Better Code

Introduction

Modern JavaScript offers powerful patterns and techniques that can significantly improve code quality, maintainability, and performance. Let's explore some of the most useful patterns every developer should know.

Async/Await Patterns

Error Handling with Async/Await

// Robust error handling pattern
async function fetchUserData(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`)
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }
    
    const userData = await response.json()
    return { data: userData, error: null }
  } catch (error) {
    console.error('Failed to fetch user data:', error)
    return { data: null, error: error.message }
  }
}

Parallel Async Operations

// Execute multiple async operations in parallel
async function loadDashboardData(userId) {
  const [userResult, postsResult, notificationsResult] = await Promise.allSettled([
    fetchUserData(userId),
    fetchUserPosts(userId),
    fetchNotifications(userId)
  ])
  
  return {
    user: userResult.status === 'fulfilled' ? userResult.value : null,
    posts: postsResult.status === 'fulfilled' ? postsResult.value : [],
    notifications: notificationsResult.status === 'fulfilled' ? notificationsResult.value : []
  }
}

Functional Programming Patterns

Composition and Currying

// Function composition
const pipe = (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value)

const addTax = (rate) => (price) => price * (1 + rate)
const addShipping = (cost) => (price) => price + cost
const formatCurrency = (price) => `$${price.toFixed(2)}`

const calculateTotal = pipe(
  addTax(0.08),
  addShipping(5.99),
  formatCurrency
)

console.log(calculateTotal(100)) // "$113.99"

Module Patterns

ES6 Modules with Default and Named Exports

// utils/api.js
export const API_BASE_URL = 'https://api.example.com'

export const httpClient = {
  async get(endpoint) {
    const response = await fetch(`${API_BASE_URL}${endpoint}`)
    return response.json()
  },
  
  async post(endpoint, data) {
    const response = await fetch(`${API_BASE_URL}${endpoint}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    })
    return response.json()
  }
}

export default httpClient

Observer Pattern

class EventEmitter {
  constructor() {
    this.events = {}
  }
  
  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = []
    }
    this.events[event].push(callback)
  }
  
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(data))
    }
  }
  
  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback)
    }
  }
}

Performance Optimization Patterns

Debouncing and Throttling

// Debounce function
function debounce(func, wait) {
  let timeout
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout)
      func(...args)
    }
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
  }
}

// Throttle function
function throttle(func, limit) {
  let inThrottle
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args)
      inThrottle = true
      setTimeout(() => inThrottle = false, limit)
    }
  }
}

Memory Management

Proper memory management is crucial for performance:

  • Remove event listeners when components unmount
  • Clear intervals and timeouts
  • Avoid memory leaks with closures
  • Use WeakMap and WeakSet for temporary references

Conclusion

These modern JavaScript patterns will help you write more maintainable, efficient, and robust code. Practice implementing these patterns in your projects to become a more effective developer.

Sanyam Jain

About Sanyam Jain

Full-Stack Developer specializing in Ruby on Rails and Next.js

Related Articles

Next.js

Advanced Next.js Patterns for Production

Explore advanced patterns and best practices for building production-ready Next.js applications.

Jan 20, 202410 min read
Ruby on Rails

Rails 7 Performance Optimization Guide

Learn how to optimize your Rails 7 applications for maximum performance and scalability.

Jan 12, 202415 min read