Streamlining Asynchronous Code

Mikey NicholsMikey Nichols
6 min read

JavaScript continues to evolve with each passing year, bringing new features and improvements that enhance developer productivity and code quality. With ECMAScript 2024 (ES15) officially being released just last month, it's time to explore the confirmed additions that are now at your fingertips. Let's dive into the features that were just made a reality.

Understanding the ECMAScript Evolution Process

Before we explore the new features, it's important to understand how JavaScript evolves. The TC39 committee, comprised of representatives from major browser vendors and JavaScript experts, oversees a rigorous four-stage process for new features:

  1. Stage 1 (Proposal): Initial idea with a champion

  2. Stage 2 (Draft): Initial specification

  3. Stage 3 (Candidate): Complete specification and initial implementations

  4. Stage 4 (Finished): Ready for inclusion in the next ECMAScript release

Only features that have reached Stage 4 are guaranteed to be part of the ES2024 specification. Let's look at what made the cut.

Official ES15 (2024) Features

1. RegExp Enhancements with the /v Flag

Regular expressions get a significant boost with the new /v flag, which introduces set operations for character classes:

// Using character set operations with the v flag
const consonantsOnly = /[[a-z]--[aeiou]]/v;
console.log("javascript".match(consonantsOnly));
// Matches: ['j', 'v', 's', 'c', 'r', 'p', 't']

// Intersection using &&
const asciiDigits = /[\p{Decimal_Number}&&[0-9]]/v;
console.log("123٤٥٦".match(asciiDigits));
// Matches: ['1', '2', '3']

This enhancement makes complex pattern matching significantly more intuitive, especially when working with internationalized content.

2. Array and TypedArray findLast() and findLastIndex()

Building on the popular find() and findIndex() methods, ES2024 introduces their backwards-searching counterparts:

const numbers = [1, 4, 10, 5, 15, 2];

// Find the last number greater than 5
const lastLargeNumber = numbers.findLast(num => num > 5);
console.log(lastLargeNumber); // 15

// Find the index of the last number greater than 5
const lastLargeNumberIndex = numbers.findLastIndex(num => num > 5);
console.log(lastLargeNumberIndex); // 4

These methods provide a convenient way to search arrays from the end instead of having to reverse an array first or use complex workarounds.

3. Object.groupBy() and Map.groupBy()

One of the most useful additions to ES2024, these methods allow you to group collection elements by a property or computed value:

const inventory = [
  { name: "asparagus", type: "vegetable" },
  { name: "banana", type: "fruit" },
  { name: "goat", type: "meat" },
  { name: "apple", type: "fruit" }
];

// Group items by type
const grouped = Object.groupBy(inventory, item => item.type);
console.log(grouped);
/*
{
  vegetable: [{ name: "asparagus", type: "vegetable" }],
  fruit: [{ name: "banana", type: "fruit" }, { name: "apple", type: "fruit" }],
  meat: [{ name: "goat", type: "meat" }]
}
*/

// Using Map.groupBy for a Map result
const groupedMap = Map.groupBy(inventory, item => item.type);
console.log(groupedMap);
// Map with the same grouping but as a Map object

This feature eliminates the need for common boilerplate code that developers have been writing for years when aggregating data.

4. Well-Formed Unicode Strings with String.prototype.toWellFormed()

Working with internationalized content gets easier with toWellFormed(), which fixes strings containing lone surrogates:

// Create a string with a lone surrogate
const problematicString = "Hello\uD800World";

// Fix the string
const fixedString = problematicString.toWellFormed();
console.log(fixedString); // "Hello�World" (with a replacement character)

// Check if a string is well-formed
const isWellFormed = !problematicString.isWellFormed();
console.log(isWellFormed); // true (it contains a lone surrogate)

This method helps prevent encoding errors when working with Unicode strings, particularly when interacting with APIs that require well-formed UTF-16.

5. Promise.withResolvers()

This utility function creates a promise along with its resolve and reject functions already extracted, simplifying common promise patterns:

// Before ES2024
function createPromiseOldWay() {
  let resolveFunc, rejectFunc;
  const promise = new Promise((resolve, reject) => {
    resolveFunc = resolve;
    rejectFunc = reject;
  });
  return { promise, resolve: resolveFunc, reject: rejectFunc };
}

// With ES2024
const { promise, resolve, reject } = Promise.withResolvers();

// Using it in an async operation
setTimeout(() => resolve("Operation complete!"), 1000);
promise.then(result => console.log(result));

This feature is particularly useful for creating promises that need to be resolved or rejected outside of their constructor.

6. Atomics.waitAsync

For developers working with shared memory and web workers, Atomics.waitAsync provides a non-blocking way to wait for a value change in a shared buffer:

// Create a shared buffer
const buffer = new SharedArrayBuffer(4);
const view = new Int32Array(buffer);

// Set initial value
view[0] = 0;

// In a worker thread, you would use
const waitPromise = Atomics.waitAsync(view, 0, 0);
waitPromise.then(result => {
  console.log("Value changed:", result);
});

// In another thread, this would wake up the waiting thread
Atomics.store(view, 0, 1);
Atomics.notify(view, 0, 1);

Unlike the blocking Atomics.wait(), this asynchronous version allows the main thread to continue execution while waiting for a value change.

Features on the Horizon: What's Coming Soon

While not part of the ES2024 release, several exciting proposals are progressing through the TC39 process and may appear in future versions:

The Temporal API (Stage 3)

The Temporal API aims to solve the many challenges of the native Date object by providing a more comprehensive, intuitive API for date and time manipulation:

// Note: This is a preview; implementation may change
// This code would require a polyfill to run today

// Create a date
const date = Temporal.PlainDate.from("2024-06-15");

// Add 10 days
const newDate = date.add({ days: 10 });
console.log(newDate.toString()); // "2024-06-25"

// Working with time zones
const now = Temporal.Now.zonedDateTimeISO();
const tokyo = now.withTimeZone("Asia/Tokyo");
console.log(tokyo.toString());

Pipeline Operator (Stage 2)

The pipeline operator would make functional programming more elegant by allowing values to flow through a series of operations:

// Note: This is a preview; implementation may change
// This code would require a transpiler to run today

// Without pipeline operator
const result = Math.round(parseFloat(String(5).padEnd(2, "0")));

// With pipeline operator (future syntax)
const pipelineResult = 5
  |> String
  |> (x => x.padEnd(2, "0"))
  |> parseFloat
  |> Math.round;

Browser Support and Using ES2024 Features Today

Browser implementations of ES2024 features will roll out gradually throughout the year. You can start using these features today with:

// Babel configuration for ES2024 features
{
  "presets": [
    ["@babel/preset-env", {
      "targets": "> 0.25%, not dead",
      "useBuiltIns": "usage",
      "corejs": 3
    }]
  ]
}

For production applications, consider using feature detection to ensure compatibility across browsers.

Future-Proof Your Code: Exploring ES2024's Powerful New Features

JavaScript continues to evolve, and ECMAScript 2024 (ES15) brings exciting new capabilities that make your code cleaner, more efficient, and more expressive. This interactive showcase demonstrates four game-changing features: Promise.withResolvers() for better async control, Object.groupBy() for elegant data organization, String.toWellFormed() for bulletproof Unicode handling, and modern array methods that streamline common operations. Whether you're building complex applications or just starting your JavaScript journey, these tools will fundamentally change how you approach everyday coding challenges. Explore each feature with our hands-on examples and discover how ES2024 can modernize your development workflow.

Conclusion

ECMAScript 2024 continues JavaScript's evolution with practical features that address real developer needs. From powerful array manipulation to better internationalization support and improved async patterns, these additions make everyday coding tasks more straightforward.

The features we've explored are just the confirmed ones that have reached Stage 4. The JavaScript ecosystem continues to evolve, with many more exciting features in the pipeline for future releases.

Are you excited to use any of these new features in your projects? Let us know in the comments which ES2024 addition you think will have the biggest impact on your daily coding!

0
Subscribe to my newsletter

Read articles from Mikey Nichols directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mikey Nichols
Mikey Nichols

I am an aspiring web developer on a mission to kick down the door into tech. Join me as I take the essential steps toward this goal and hopefully inspire others to do the same!