Generators is a coroutine (coroutine) style of Javascript. It refers to functions that can be paused and then resumed during execution. The function is accompanied by asterisk symbols in the function, such as function*, and some characteristic keywords in the function, such as yield and yield*.
function* generatorFn () { console.log('look ma I was suspended')}var generator = generatorFn() // [1]setTimeout(function () { generator.next() // [2]}, 2000)The [1] and [2] marked in the code are explained as follows:
1. This is a generator that starts with a pause. There is no console output at this time.
2. Only by calling its next() method can the generator be executed and run until it encounters the next yield keyword or return. Now we have the console output.
Let’s look at another case:
function *generator() { console.log('Start!'); var i = 0; while (true) { if (i < 3) yield i++; }}var gen = generator();The above code is similar to the first one, but there is an additional yield keyword in the generator function. When the above code is called, it will not be executed immediately, but will pause the standby state, so there will be no Start output. It is not executed until its next() call.
var ret = gen.next();// Start!console.log(ret);// {value: 0, done: false}The above ret is the generator result. It has two properties:
■value, yield value in generator function,
■done, this is a flag indicating whether the generator function returns.
Continue the code as follows:
console.log(gen.next());// {value: 1, done: false}console.log(gen.next());// {value: 2, done: false}console.log(gen.next());// {value: undefined, done: true}Generator has no mystery in synchronous programming, and is especially suitable for asynchronous programming.
Generator has two characteristics:
1. You can choose to jump out of a function, let the external code decide when to jump back to this function and continue execution.
2. Able to perform asynchronous control.
Look at the following asynchronous execution code:
var gen = generator();console.log(gen.next().value);setTimeout(function() { console.log(gen.next().value); console.log('first step');}, 1000);console.log('second step');The output is:
0
Step 2
1
first step
In other words, you will not wait for the timeout to end at setTimeout, but will continue directly with the "second step" and will not be blocked at setTimeout.
Let's look at another piece of code:
function* channel () { var name = yield 'hello, what is your name?' // [1] return 'well hi there ' + name}var gen = channel()console.log(gen.next().value) // hello, what is your name? [2]console.log(gen.next('billy')) // well hi there billy [3]You can also use * during traversal:
function* iter () { for (var i = 0; i < 10; i++) yield i}for (var val of iter()) { console.log(val) // outputs 1?―?9}Common misunderstandings
Since I can pause a function execution, should I let them execute in parallel? No, because Javascript is a single thread, and if you want to seek performance improvements, generator is not your dish.
For example, the following code executes Fibonacci numbers separately:
function fib (n) { var current = 0, next = 1, swap for (var i = 0; i < n; i++) { swap = current, current = next next = swap + next } return current} function* fibGen (n) { var current = 0, next = 1, swap for (var i = 0; i < n; i++) { swap = current, current = next next = swap + next yield current }}The performance results are as follows: (The higher the better)
Results:
Regular 1263899
generator 37541
Generators shine
Generators can simplify the complexity of functions in JavaScript.
Lazy assignment
Although lazy assignment can be implemented using JS closures, using yield will greatly simplify. Through pause and recovery, we can get numeric values when we need it. For example, the above fibGen function can pull new values when we need it:
var fibIter = fibGen(20)var next = fibIter.next()console.log(next.value)setTimeout(function () { var next = fibIter.next() console.log(next.value)},2000) Of course, it also uses a for loop: it is still lazy to assign for (var n of fibGen(20) { console.log(n)}Infinite Sequence
Because you can be lazy to assign values, you may perform some Haskell tricks, similar to infinite sequences. Here you can yield the number of an infinite sequence.
function* fibGen () { var current = 0, next = 1, swap while (true) { swap = current, current = next next = swap + next yield current }}Let's look at the lazy assignment of a Fibonacci stream and ask it to return the first Fibonacci number after 5000:
for (var num of fibGen()) { if (num > 5000) break}console.log(num) // 6765Asynchronous process control
Using generators to implement asynchronous process control, most commonly various promise library packages, so how does it work?
In the Node world, everything is related to callbacks, which is our low-level asynchronous function. We can use generators to build a communication channel, so as to write asynchronous code in the style of synchronous programming.
run(function* () { console.log("Starting") var file = yield readFile("./async.js") // [1] console.log(file.toString())})Note 1 means that the program will continue before waiting for async.js to return the result.
genify is a framework that brings generators into a normal programming environment, using the following:
npm install genify for installation, the code is as follows:
var Q = require('q');var fs = require('fs');var genify = require('genify'); // wrap your object into genify functionvar object = genify({ concatFiles: function * (file1, file2, outFile) { file1 = yield Q.nfcall(fs.readFile, file1); file2 = yield Q.nfcall(fs.readFile, file2); var concated = file1 + file2; yield Q.nfcall(fs.writeFile, outFile, concated); return concated; }}); // concatFiles is a generator function that uses the powerful capabilities of generators. object.concatFiles('./somefile1.txt', './somefile2.txt', './concated.txt').then(function (res) { // do something with result}, function (err) { // do something with error});The above detailed explanation of using Javascript Generators in Node.js is all the content I share with you. I hope you can give you a reference and I hope you can support Wulin.com more.