I am trying to figure out how to do async calls using promises and generators (without 3rd party libraries). Most of the examples I found on the Internet are either incomplete or confusing (at least to me), so I decided to try and write the code myself.
I would really appreciate it if someone could review the code and provide comments and suggestions for improving it.
function getJSON(url) {
return new Promise((resolve, reject) => {
const https = require("https");
try {
https.get(url, (response) => {
let data = "";
response.on("data", (part) => {
data += part;
});
response.on("end", () => {
try {
resolve(JSON.parse(data));
}
catch(e) {
reject("Error parsing data");
}
});
}).on("error", () => {
reject("Error downloading data");
});
}
catch(e) {
reject("Error: " + e.message);
}
});
}
function request(generator) {
var iterator = generator();
function process(result) {
if (result.done) {
return;
}
const value = result.value;
if (value instanceof Promise) {
value.then(
(data) => {
console.log(data);
process(iterator.next());
}
)
.catch(
err => {
iterator.throw(err);
}
);
}
}
try {
process(iterator.next());
}
catch(e) {
iterator.throw(e);
}
}
function *DataGenerator() {
try {
yield getJSON("https://jsonplaceholder.typicode.com/posts/1");
yield getJSON("https://jsonplaceholder.typicode.com/posts/2");
// yield getJSON("https://jsonplaceholder.typicode.com/"); // Parsing error
// yield getJSON(""); // Domain name error
}
catch (e) {
console.log(e);
}
}
// Run
console.log("Before");
request(DataGenerator);
console.log("After");
This is also available as a repo.
2 Answers 2
The code looks pretty good - like a nice application of generators and iterators for promises.
The only thing I could think of that could be updated is the iterator
variable in the request()
function could be declared with the const statement, since it doesn't appear to be re-assigned (unless I am missing something).
var iterator = generator();
Then in that nested function process()
, did you ever see the first conditional (i.e. result.done
) have a truthy value? I tried running it a few times but never saw that occur...
function process(result) { if (result.done) { return; }
Why do not use async / await functions? Its just syntactic sugar for promises / generators. Check this vanilla JS snippet, is live:
var url1 = 'https://jsonplaceholder.typicode.com/posts/2'
var url2 = 'https://jsonplaceholder.typicode.com/posts/3'
async function mimicSyncInside () {
console.log('Before')
console.log(await fetch(url1).then(resp => resp.json()))
console.log(await fetch(url2).then(resp => resp.json()))
console.log('After')
}
mimicSyncInside()
-
\$\begingroup\$ There are many reasons. One of them is to better understand async/await (take a look behind the scenes sort of thing). Also, it is not either/or type of thing (eg. if you want to parallelize async/await tasks you need to use Promise.all) so depending on situation one might actually prefer using promises and generators over async/await. \$\endgroup\$ArminMeth– ArminMeth2017年09月18日 16:11:32 +00:00Commented Sep 18, 2017 at 16:11
-
\$\begingroup\$ BTW, to mimic the same behavior, the aync/await code should be
console.log('Before')
then the async function with await tasks and thenconsole.log('After')
\$\endgroup\$ArminMeth– ArminMeth2017年09月18日 16:18:21 +00:00Commented Sep 18, 2017 at 16:18 -
\$\begingroup\$ And your code works? In this order? Before - post1 - post2 - after? \$\endgroup\$user145018– user1450182017年09月18日 18:07:25 +00:00Commented Sep 18, 2017 at 18:07
Explore related questions
See similar questions with these tags.