In the following code:
function so() {
console.log('inside the timer')
}
function* sogen() {
const callback = yield;
setTimeout(callback, 2000);
return 1;
}
function() {
var gen = sogen();
gen.next(so), gen.next(so);
}()
Why am I never reaching function so
?
Introduction to JavaScript setTimeout()The setTimeout() sets a timer and executes a callback function after the timer expires. In this syntax: cb is a callback function to be executed after the timer expires. delay is the time in milliseconds that the timer should wait before executing the callback function.
If you call setTimeout() with a time of 0 ms, the function you specify is not invoked right away. Instead, it is placed on a queue to be invoked “as soon as possible” after any currently pending event handlers finish running.
If you're using TypeScript, you can pass the function as a parameter, like this: setTimeout(this. tip. destroy, 1000);
setTimeout(callback, 0) executes the callback with a delay of 0 milliseconds. Open the demo and check the console. You'll notice that 'Resolved!'
tl;dr you need to wrap your IIFE with parentheses or to not use an IIFE at all.
Your use of generators is fine, and once you add the parens, everything works as normal.
Note that you don't really need a IIFE to run your code, but my answer below explains why what you have is not working.
The main problem you have is in this code:
function() {
var gen = sogen();
gen.next(so);
gen.next(so);
}()
This will produce an error similar to:
Uncaught SyntaxError: Unexpected token (
The problem here is that you are trying to use a function declaration as a function expression.
From MDN (emphasis mine):
A function expression is very similar to and has almost the same syntax as a function statement (see function statement for details). The main difference between a function expression and a function statement is the function name, which can be omitted in function expressions to create anonymous functions. A function expression can be used as a IIFE (Immediately Invoked Function Expression) which runs as soon as it is defined. See also the chapter about functions for more information.
This means that in order to execute a function immediately, you need to use a function expression rather than a statement.
One common way of writing a function expression is to wrap the function in parentheses:
function a() { return 'a'; } // Function declaration
(function b() { return 'b'; }) // Function expression
To convert that into an IIFE, you can add the ()
invocation parens at the end:
(function c() { return 'c'; })() // IIFE
which calls the function immediately. Note that I prefer to put the invocation parentheses inside the wrapping parens but this is just a stylistic choice and works in the same way:
(function c() { return 'c'; }()) // IIFE
Here's the code from the answer, plus the parens wrapping the IIFE:
function so() {
console.log('inside the timer');
}
function* sogen() {
const callback = yield;
setTimeout(callback, 2000);
return 1;
}
(function() {
const gen = sogen();
gen.next(so);
gen.next(so);
}())
Alternatively, simply remove your IIFE:
const gen = sogen();
gen.next(so);
gen.next(so);
or if you need a function declaration, call the function on the next line:
function run() {
const gen = sogen();
gen.next(so);
gen.next(so);
}
run();
The snipped you provided should now be working (except for the syntax error in the IIFE). I have rewritten it for clarity.
function so() {
console.log('inside the timer')
}
function* sogen()
{
const callback = yield; // line 1
setTimeout(callback, 2000); // line 2
return 1; // line 3
}
Now let's see how using the iterator returned from sogen
we can call so
.
var iter = sogen();
We have created an iterator. Calling the next
method of the iterator we can advance the execution of the sogen
generator.
iter.next();
After this call the state of the iterator is now frozen on line 1 of sogen
. The yield
was encountered and {value: undefined, done: false}
was returned from the .next()
call. At this point we are ready to pass our callback.
iter.next(so);
We have passed the callback into the next
method and the execution resumes at line 1. The callback
variable has now the value of so
function. Continuing onto line 2 - setTimeout is called. In two seconds our so
function will be called. But before it is the code continues to line 3. The .next(so)
call returns {value: 1, done: true}
. Now we wait.
After two seconds you should see that inside the timer
has been logged to the console.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With