What is a Generator?
There is an introduction in ES6 to a new way of working with functions and iterators as generator functions. A generator is a function that gives the power of execution in the hands of the user, what it does is that it can stop at a specific point and returns the power of execution from that point onwards to the user. In short, a generator appears to be a function but it behaves like an iterator. Let's discuss it with an example and comparison with Async/Await.
Example
Generator:
function* generator() {
// yield Keyword is where the execution stops and an object is returned
const user = yield getUserFromDB();
return (user + " Correctly Received");
}
const iterator = generator();
// It will run the generator function up to the first yeild keyword
// But the execution will be halted right after calling the 'getUserFromDB' function but right before assigning it to the const user(Very important to note here)
const iteration = iterator.next();
// Generator returns an Object after calling the next() function
// iteration will return the unresolved promise {value: Promise{}, done: false}
console.log(iteration);
// Why is the done's value false?
// You need to understand that, the last yield keyword is like the return statement in the normal function
// while previous yield keywords are like mini returns but they do not terminate the generator
// Only the final yield keyword returns the done:true because it tells that the generator function is now completed, its state is moved to "completed" state.
// It is called when the promise resolves
iteration.value.then( resolvedValue => {
console.log(resolvedValue); // let's say it's "Got some Users"
// Now, we can continue the execution by
const nextIteration = iterator.next(resolvedValue);
// Notice, we are using the very first const we initialised with
// Another amazing thing to notice
// We can pass the value to the generator function as well
// Which can become the part of the next returned object :-)
console.log(nextIteration);
// We get the final value: {value: "Got some Users Correctly Received", done: true}
// See, Now Done is true
}
Async/Await:
async function testing() {
const users = await getUsersFromDB();
return (users + " Correctly Received");
}
// That's it with async/await :p
The async function declaration defines an asynchronous function — a function that is an AsyncFunction object. Asynchronous functions operate in a separate order than the rest of the code via the event loop, returning an implicit Promise as its result. But the syntax and structure of code using async functions looks like standard synchronous functions.
What is the difference between "Await" and "Yield" Keywords you ask?
Yield can be considered to be the binding block of await. Yield takes the value it's given and passes it to its caller.
- The caller can do whatever it wishes with that value
- Later the caller may give a value back to the generator(via generator.next()), which becomes the result of the yield expression.
- Or an error that will appear to be thrown by the yield expression.
async-await can be considered to use yield.
- At the caller(i.e. the async-await driver) will wrap the value in a promise using a similar algorithm to new Promise(r => r(value)) (note, not Promise.resolve, but that's not a big deal).
- It then waits for the promise to resolve. If it fulfils, it passes the fulfilled value back.
- If it rejects, it throws the rejection reason as an error.
In this Answer's Summary:
Utility of async-await is to use yield and unwrap the yielded value as a promise and pass it's resolved value back, repeating until the function returns its final value.
Now there's an another question: Is it possible to reset Generator?
Once a generator enters the "completed" state, it never leaves it and its associated execution context is never resumed. Any execution state associated with generator can be discarded at this point.
Top comments (0)