co
The ultimate generator based flow-control goodness for nodejs (supports thunks, promises, etc)
A JavaScript library that made asynchronous Node.js code readable before async/await existed, by running generator functions and handling promises automatically, now mostly used in older codebases.
Co is a small JavaScript library that made it easier to write asynchronous code in Node.js before async/await was added to the language. In Node.js, many operations like reading files or making network requests happen asynchronously, meaning your program sends off a request and continues running while waiting for a result. Managing this flow cleanly was tricky in older JavaScript, and co was one of the popular tools that helped.
The library works by running generator functions, a JavaScript feature that lets a function pause at certain points and resume later. Co takes over when the function pauses, waits for the underlying operation to finish, and then continues the function with the result. From the programmer's perspective, the code reads more like straightforward top-to-bottom steps rather than nested callbacks.
Co version 4, covered in the README, switched its core mechanism to use promises, which had become the standard way to represent future values in JavaScript. Co can handle yielding a single promise, an array of promises to run in parallel, an object whose values are promises, or other generator functions. Errors can be caught using the standard try/catch syntax inside the generator, which was not straightforward with older callback-style code.
The README notes that co was explicitly described as a stepping stone toward the async/await syntax that was coming to JavaScript. Modern JavaScript (Node.js version 4 and later, all current browsers) has async/await built in, which accomplishes the same goal without any library. Co is still widely used in older codebases but is generally not the first choice for new projects written against current JavaScript standards.
Installation is through npm. The project is open-source under the MIT license.
Where it fits
- Refactor old callback-heavy Node.js code to use generator-based flow control that reads top-to-bottom
- Run multiple async operations like database queries in parallel and collect all results before continuing
- Handle async errors with try/catch inside a generator function instead of managing nested error callbacks
- Understand legacy Node.js codebases that use co before migrating them to modern async/await