In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)05/31 Report--
Most people do not understand the knowledge points of this article "the method of automatic execution of Generator in ES6", so the editor summarizes the following contents, detailed contents, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this article "the method of automatic execution of Generator in ES6".
Single asynchronous task
Var fetch = require ('node-fetch'); function* gen () {var url =' https://api.github.com/users/github'; var result = yield fetch (url); console.log (result.bio);}
To get the final execution result, you need to do this:
Var g = gen (); var result = g.next (); result.value.then (function (data) {return data.json ();}). Then (function (data) {g.next (data);})
First execute the Generator function to get the ergodic object.
Then use the next method to execute the first phase of the asynchronous task, fetch (url).
Note that because fetch (url) returns a Promise object, the value of result is:
{value: Promise {}, done: false}
Finally, we add a then method to the Promise object, first format the returned data (data.json ()), and then call g.next to pass in the obtained data, so that we can execute the second phase of the asynchronous task, and the code execution is complete.
Multiple asynchronous tasks
In the last section, we only called one interface, so if we call multiple interfaces and use multiple yield, we will continue to nest in the then function.
So let's take a look at performing multiple asynchronous tasks:
Var fetch = require ('node-fetch'); function* gen () {var R1 = yield fetch (' https://api.github.com/users/github'); var R2 = yield fetch ('https://api.github.com/users/github/followers'); var R3 = yield fetch (' https://api.github.com/users/github/repos');) Console.log ([r1.bio, R2 [0] .login, R3 [0] .full _ name] .join ('\ n'));}
In order to get the final execution result, you may have to write:
Var g = gen (); var result1 = g.next (); result1.value.then (function (data) {return data.json ();}) .then (function (data) {return g.next (data) .value;}) .then (function (data) {return data.json ();}) .then (function (data) {return g.next (data) .value}) .then (function (data) {return data.json () }) .then (function (data) {g.next (data)})
But I know you don't want to write like this...
In fact, using recursion, we can write:
Function run (gen) {var g = gen (); function next (data) {var result = g.next (data); if (result.done) return; result.value.then (function (data) {return data.json ();}). Then (function (data) {next (data);});} next ();} run (gen)
The key is to return a Promise object when yield, add a then method to the Promise object, execute the onFullfilled function in then when the asynchronous operation is successful, and g.next in the onFullfilled function to allow Generator to continue execution, then return a Promise, execute g.next on success, and then return.
Initiator function
In the run initiator function, we format the data in the then function data.json (), but in more general cases, such as yield following a Promise directly, rather than the Promise returned by a fetch function, because without the json method, the code will report an error. So in order to be more versatile, together with this example and initiator, we modify it to:
Var fetch = require ('node-fetch'); function* gen () {var R1 = yield fetch (' https://api.github.com/users/github'); var json1 = yield r1.json (); var R2 = yield fetch ('https://api.github.com/users/github/followers'); var json2 = yield r2.json (); var R3 = yield fetch (' https://api.github.com/users/github/repos');) Var json3 = yield r3.json (); console.log ([json1.bio, json2 [0] .login, json3 [0] .full _ name] .join ('\ n'));} function run (gen) {var g = gen (); function next (data) {var result = g.next (data); if (result.done) return; result.value.then (function (data) {next (data)) });} next ();} run (gen)
As long as the yield is followed by a Promise object, we can use this run function to execute the Generator function automatically.
Callback function
Does yield have to be followed by a Promise object to ensure the automatic execution of Generator? What if it's just a callback function? Let's look at an example:
First, let's simulate a normal asynchronous request:
Function fetchData (url, cb) {setTimeout (function () {cb ({status: 200, data: url})}, 1000)}
We transform this function into:
Function fetchData (url) {return function (cb) {setTimeout (function () {cb ({status: 200, data: url})}, 1000)}}
For Generator functions like this:
Function* gen () {var R1 = yield fetchData ('https://api.github.com/users/github'); var R2 = yield fetchData (' https://api.github.com/users/github/followers'); console.log ([r1.data, r2.data] .join ('\ n'));}
If you want to get the final result:
Var g = gen (); var R1 = g.next (); r1.value (function (data) {var R2 = g.next (data); r2.value (function (data) {g.next (data);});})
If we write like this, we will face the same problem as in the first section, that is, when using multiple yield, the code will be nested in a loop.
Recursion is also used, so we can transform it into:
Function run (gen) {var g = gen (); function next (data) {var result = g.next (data); if (result.done) return; result.value (next);} next ();} run (gen)
Run
From this we can see that the automatic execution of the Generator function needs a mechanism, that is, when the asynchronous operation has a result, it can automatically hand back the execution power.
And there are two ways to do this.
(1) callback function. The asynchronous operation is wrapped, the callback function is exposed, and the execution authority is returned in the callback function.
(2) Promise object. The asynchronous operation is wrapped as a Promise object and the execution authority is handed back with the then method.
In each of the two methods, we have written a run initiator function, so can we combine these two methods and write a general run function? Let's try this:
/ / first edition function run (gen) {var gen = gen (); function next (data) {var result = gen.next (data); if (result.done) return; if (isPromise (result.value)) {result.value.then (function (data) {next (data);}) } else {result.value (next)}} next ()} function isPromise (obj) {return 'function' = = typeof obj.then;} module.exports = run
In fact, the implementation is very simple, to determine whether result.value is Promise, it is to add the then function, not directly executed.
Return Promise
We have written a nice initiator function that supports yield followed by callback functions or Promise objects.
Now there is a question to think about, that is, how do we get the return value of the Generator function? And if there is an error in the Generator function, such as fetch an interface that does not exist, how can the error be caught?
It's easy to think of Promise. If the initiator function returns a Promise, we can add the then function to the Promise object. When all the asynchronous operations are successful, we execute the onFullfilled function, and if there is any failure, we execute the onRejected function.
Let's write a page:
/ second edition function run (gen) {var gen = gen (); return new Promise (function (resolve, reject) {function next (data) {try {var result = gen.next (data);} catch (e) {return reject (e) } if (result.done) {return resolve (result.value)}; var value = toPromise (result.value); value.then (function (data) {next (data);}, function (e) {reject (e)}) } next ()} function isPromise (obj) {return 'function' = = typeof obj.then;} function toPromise (obj) {if (isPromise (obj)) return obj; if (' function' = = typeof obj) return thunkToPromise (obj); return obj;} function thunkToPromise (fn) {return new Promise (function (resolve, reject) {fn (function (err, res) {if (err) return reject (err)) Resolve (res);} module.exports = run
It is very different from the first edition:
First, we return a Promise, and when result.done is true, we will resolve (result.value). If an error occurs during execution and is held by catch, we will reject (e) the reason.
Second, we will use thunkToPromise to wrap the callback function as a Promise, and then uniformly add the then function. It is worth noting here that in the thunkToPromise function, we follow the principle of error first, which means that when we deal with the callback function:
/ / Analog data request function fetchData (url) {return function (cb) {setTimeout (function () {cb (null, {status: 200, data: url}), 1000)}}
On success, the first parameter should return null, indicating that there is no error reason.
Optimize
We made the code a little more concise and elegant on the basis of the second edition, and the final code is as follows:
/ / third edition function run (gen) {return new Promise (function (resolve, reject) {if (typeof gen = = 'function') gen = gen (); / / if gen is not an iterator if (! gen | | typeof gen.next! = =' function') return resolve (gen) onFulfilled (); function onFulfilled (res) {var ret Try {ret = gen.next (res);} catch (e) {return reject (e);} next (ret);} function onRejected (err) {var ret; try {ret = gen.throw (err) } catch (e) {return reject (e);} next (ret);} function next (ret) {if (ret.done) return resolve (ret.value); var value = toPromise (ret.value); if (value & & isPromise (value)) return value.then (onFulfilled, onRejected) Return onRejected (new TypeError ('You may only yield a function, promise' + 'but the following object was passed: "' + String (ret.value) +'");})} function isPromise (obj) {return 'function' = = typeof obj.then;} function toPromise (obj) {if (isPromise (obj)) return obj; if (' function' = = typeof obj) return thunkToPromise (obj); return obj } function thunkToPromise (fn) {return new Promise (function (resolve, reject) {fn (function (err, res) {if (err) return reject (err); resolve (res);});} module.exports = run
Co
If we write this initiator function a little bit more, we will be equivalent to writing a co. In fact, the above code does come from co.
And what is co? Co is a small module released by the great god TJ Holowaychuk in June 2013 for the automatic execution of Generator functions.
If you use the co module directly, these two different examples can be abbreviated as:
/ / yield is followed by a Promisevar fetch = require ('node-fetch'); var co = require (' co'); function* gen () {var R1 = yield fetch ('https://api.github.com/users/github'); var json1 = yield r1.json (); var R2 = yield fetch (' https://api.github.com/users/github/followers'); var json2 = yield r2.json ()) Var R3 = yield fetch ('https://api.github.com/users/github/repos'); var json3 = yield r3.json (); console.log ([json1.bio, json2 [0] .login, json3 [0] .full _ name] .join ('\ n'));} co (gen); / / yield is followed by a callback function var co = require ('co') Function fetchData (url) {return function (cb) {setTimeout (function () {cb (null, {status: 200, data: url}), 1000)} function* gen () {var R1 = yield fetchData ('https://api.github.com/users/github'); var R2 = yield fetchData (' https://api.github.com/users/github/followers');) Console.log ([r1.data, r2.data] .join ('\ n'));} co (gen); the above is about the method of automatic execution of Generator in ES6. I believe you all have some understanding. I hope the content shared by the editor will be helpful to you. If you want to learn more about the relevant knowledge, please follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.