Generator function in JavaScript

·

3 min read

Introduction

JavaScript generator functions are a special type of function that allows you to pause and resume the execution of a function. They are defined using the function* syntax and use the yield keyword to pause execution. This can be useful in a variety of situations, such as iterating through large data sets, implementing an iterator, creating infinite sequences and handling concurrency and asynchrony.

Think of it like hitting the pause button on a movie. You can then use the next() method to resume the function and move on to the next value. It's like hitting play again on that movie. Here is an example of a generator function:

function* myGenerator() {
    yield 1;
    yield 2;
    yield 3;
}
const generator = myGenerator();
console.log(generator.next().value);  // 1
console.log(generator.next().value);  // 2
console.log(generator.next().value);  // 3

Benefits of using generator functions

Generator functions have several benefits, such as:

  • Memory efficiency: Generator functions are memory efficient as they do not load all the data in memory at once.

  • Control over the flow of a program: Generator functions provide more control over the flow of the program because they can be paused and resumed.

  • Concurrency and Asynchrony: Generator functions can be used to handle concurrency and asynchrony more efficiently.

Memory efficient method for reading a large file

So let's say you're working with a big dataset, and you only want to work with one chunk at a time. That's where generator functions come in handy. You can use the yield keyword to pause the function after working with one chunk, then use next() to move on to the next chunk. This way you don't have to load the whole dataset into memory at once and it's more memory efficient.

// Reading a large file content using generator function
function* readFile(file) {
    let data = '';
    let line;
    while(line = yield readLine(file)) {
        data += line;
    }
    return data;
}

Concurrency and asynchrony

Generator functions are great for handling concurrency and asynchrony. It's like having multiple people working on a project at the same time, but instead of people, it's your code.

Normally when you're working with multiple tasks that need to happen at the same time, it can get pretty messy and hard to keep track of. But with generator functions, you can use the yield keyword to pause the execution of one task and move on to another task. So, you can use the yield keyword to wait for a task to finish, like fetching data from an API, before moving on to the next task. This makes it super easy to handle concurrent tasks without cluttering your code.

// Asynchronous control flow using generators
function* fetchData() {
    const data1 = yield fetch('url1');
    const data2 = yield fetch('url2');
    return [data1, data2];
}

And as for asynchrony, generator functions can be used in conjunction with JavaScript's built-in promises to handle asynchronous code. It allows you to write asynchronous code that looks and behaves like synchronous code, making it easy to understand and maintain.

Iteration

Generator functions are well suited for iteration because they can be paused and resumed multiple times, allowing them to return multiple values. Generator functions provide more control over the flow of the iteration and can handle infinite sequences.

function* myGenerator() {
    for (let i = 0; i < 3; i++) {
        yield i;
    }
}
const generator = myGenerator();
console.log(generator.next().value);  // 0
console.log(generator.next().value);  // 1
console.log(generator.next().value);  // 2

Conclusion

Overall, generator functions are pretty versatile and can be used in a variety of situations, like creating infinite sequences, handling concurrency and asynchrony and much more.