You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/blog-md/2025/17-12/generator-generation.md
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,21 +6,21 @@ subtitle: 17 December 2025
6
6
description: Converting callback based APIs into Async Generators in JavaScript/Typescript
7
7
---
8
8
9
-
So I was just going to write a short post about this handy function I made but I thought it would be a nice opportunity to build a little bit more of an understanding around the topic of generators more broadly.
9
+
So I was just going to write a short post about this handy function I made, but I thought it would be a nice opportunity to build a little bit more of an understanding around the topic of generators more broadly
10
10
11
-
Our end goal is going to be to define an abstraction that will allow us to convert any Callback-Based API into an Async Generator. Now, if those words don't mean much to you then welcome to the other side of JavaScript. If you're just here for the magic function however - feel free to skip to the end
11
+
Our end goal is going to be to define an abstraction that will allow us to convert any Callback-Based API into an Async Generator. Now, if those words don’t mean much to you, then welcome to the other side of JavaScript. If you’re just here for the magic function, however, feel free to skip to the end
12
12
13
13
# Promises
14
14
15
15
Before diving into the complexity of generators, we're going to quickly kick off with a little introduction to `Promises` and how they relate to `async/await` and callback code
16
16
17
-
Promises are used to make async code easier to work with and JavaScript has some nice syntax - like `async/await` that makes code using promises easier follow and understand. They're also the common way to represent async operations which is exactly what we're going to use them for.
17
+
Promises are used to make async code easier to work with and JavaScript has some nice syntax - like `async/await` that makes code using promises easier follow and understand. They're also the common way to represent async operations which is exactly what we're going to use them for
18
18
19
19
Before we can dive right into implementing our function for creating an `AsyncGenerator` from a callback based API, it's important to understand how we might go about wrapping a callback based API into a `Promise`
20
20
21
21
## Creating Promises from Callbacks
22
22
23
-
Often we end up in cases where we've got some code that is callback based - this is a function, for example `setTimeout`, that will invoke the rest of our code asynchronously when some task is done or event is received.
23
+
Often we end up in cases where we've got some code that is callback based - this is a function, for example `setTimeout`, that will invoke the rest of our code asynchronously when some task is done or event is received
24
24
25
25
A simple example of a callback based function is `setTimeout` which will resume the execution of our code after some specified amount of time:
26
26
@@ -30,7 +30,7 @@ setTimeout(() => {
30
30
}, 1000)
31
31
```
32
32
33
-
A common usecase is to convert this to a `Promise` so that consumers can work with this using `async` functions and `await`ing the relevant function call.
33
+
A common usecase is to convert this to a `Promise` so that consumers can work with this using `async` functions and `await`ing the relevant function call
34
34
35
35
The basic method for doing this consists of returning a `Promise` and handling the rejection or resolution within the callback. For example, we can create a promise-based version of `setTimeout` using this approach:
36
36
@@ -57,7 +57,7 @@ await sleep(1000)
57
57
console.log('done')
58
58
```
59
59
60
-
Granted, this isn't a huge difference - the value of this comes from when we have multiple of these kinds of calls nested within each other. Callback code is notorious for it's tendency towards chaos. My rule of thumb on this is basically "less indentation is easier to understand". And if we can avoid indentation and keep our code flat we can focus on the essential complexity of our application and not the cognitive load that comes with confusing scope, syntax, and callbacks.
60
+
Granted, this isn't a huge difference - the value of this comes from when we have multiple of these kinds of calls nested within each other. Callback code is notorious for its tendency towards chaos. My rule of thumb on this is basically "less indentation is easier to understand". And if we can avoid indentation and keep our code flat we can focus on the essential complexity of our application and not the cognitive load that comes with confusing scope, syntax, and callbacks
61
61
62
62
This is such a common problem in the JavaScript world, that Node.js even has a builtin function `node:util` called `promisify` that converts Node.js style callback functions into promise-based ones
63
63
@@ -74,7 +74,7 @@ async function doWork(){
74
74
}
75
75
```
76
76
77
-
The `doWork` function returns `Promise`, this is because the `async` keyword is some syntax sugar for creating a `Promise`.
77
+
The `doWork` function returns `Promise`, this is because the `async` keyword is some syntax sugar for creating a `Promise`
78
78
79
79
## Promises vs Async
80
80
@@ -98,7 +98,7 @@ function getNumber() {
98
98
99
99
## Promise.withResolvers
100
100
101
-
Another pattern that often comes us is the need to reach into the `Promise` constructor and grab onto it's`resolve` and `reject` methods and pass them around so that we can "remotely" compelete a `Promise`, as per MDN, the common pattern for doing this looks something like so:
101
+
Another pattern that often comes us is the need to reach into the `Promise` constructor and grab onto its`resolve` and `reject` methods and pass them around so that we can "remotely" compelete a `Promise`, as per MDN, the common pattern for doing this looks something like so:
102
102
103
103
```ts
104
104
function withResolvers<T>() {
@@ -123,11 +123,11 @@ Now that we've got an understanding of Promises, it's time to talk about Iterato
123
123
124
124
# Iterators and Generators
125
125
126
-
Iterators and generators enable iteration to work in JavaScript and are what lies behind objects that are iterable by way of a `for ... of` loop.
126
+
Iterators and generators enable iteration to work in JavaScript and are what lies behind objects that are iterable by way of a `for ... of` loop
127
127
128
128
## Iterator
129
129
130
-
An iterator is basically an object that will return a new value whenever it's`next` method is called.
130
+
An iterator is basically an object that will return a new value whenever its`next` method is called
131
131
132
132
A simple iterator can be defined as an object that has a `next` method that returns whether it's `done` or not.
133
133
@@ -263,7 +263,7 @@ for await (const v of countToAsync(5)) {
263
263
}
264
264
```
265
265
266
-
Interesting right? We're now using a `for await ... of` loop. If you were to run this, you'd also notice that there's a little pause between each value being logged.
266
+
Interesting right? We're now using a `for await ... of` loop. If you were to run this, you'd also notice that there's a little pause between each value being logged
267
267
268
268
# Unwrapping the Generator
269
269
@@ -347,7 +347,7 @@ Just like when defining the Async Generator before, we're just calling `sleep` b
347
347
348
348
# Creating Generators from Callback Functions
349
349
350
-
Well, it's been a long way, but we finally have all the tools we need to turn a callback based method into an iterator. So far, we've been using `setTimeout` for our callbacks, but generators return multiple values. We're going to create a little modified version of `setInterval` for this so that we can play around.
350
+
Well, it's been a long way, but we finally have all the tools we need to turn a callback based method into an iterator. So far, we've been using `setTimeout` for our callbacks, but generators return multiple values. We're going to create a little modified version of `setInterval` for this so that we can play around
351
351
352
352
The version we'll define is called `countInterval` and will emit a new number until the given value and then stop, this looks like so:
0 commit comments