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);
}()
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
?
- let response = await soasync(); – Osama Commented Oct 16, 2018 at 22:18
-
2
yield
itself is not being used as a callback.yield
produces a value (whatever was passed to.next()
) and the value is assigned tocallback
. – Ry- ♦ Commented Oct 16, 2018 at 23:18 - 1 Please don't change question, @Aioros answer is weird now. It is better to create another question – Buggy Commented Oct 17, 2018 at 8:50
-
add parentheses around IIFE function
(function(){ var gen = sogen(); gen.next(so), gen.next(so); })()
– Buggy Commented Oct 17, 2018 at 8:51
4 Answers
Reset to default 4 +25tl;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.
Function declarations vs Function expressions
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 mon 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.
In your snippet, sogen
is not a regular function, it's a generator, as indicated by the *
.
You can call the generator to obtain what is basically an iterator, that can be controlled with the method .next()
and can pause its execution every time it encounters the yield
keyword.
var it = sogen();
it.next();
The assignment you have there (const callback = yield
) will be resolved by the subsequent .next() call, like:
it.next(function myCallback() { /* ... */ });
The generator will then keep running until the next yield
or the end of the function.
Here you are using generator function as an observer.
when you create a generator object it is not actually invoked.
when you call gen.next(so) for the first time, it acts as an invoking call to the generator and the value passed to it is ignored.(the first invocation advances execution to the first yield.)
on the second call to gen.next(so) yield receives 'function so(){}' and the rest of the code is executed.
Please have a look at this link to have more clarity : generator function as observer
Your working snippet
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745275281a4620001.html
评论列表(0条)