Skip to content

Instantly share code, notes, and snippets.

@ObsidianCat
Created December 1, 2018 11:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ObsidianCat/8f260677ae344cf7023c3f7fecf33242 to your computer and use it in GitHub Desktop.
Save ObsidianCat/8f260677ae344cf7023c3f7fecf33242 to your computer and use it in GitHub Desktop.
const { getRandomWordSync, getRandomWord } = require("word-maker");
const fs = require("fs");
console.log("It works!");
// YOUR CODE HERE
//Additional functions
//asynchronous in loop
async function asyncInLoopWithPromiseAllInOrder(){
const promises = [];
const results = []
for (let i = 1; i <= 100; i++) {
//Work around, to avoid fast fail of Promise.all()
//Push promises with attached catch
promises.push(
getRandomWord({ withErrors: true })
.then(value => {
results[i-1] = `${i}: ${value}`;
})
.catch(() => {
results[i-1] = `${i}: Doh!`;
})
);
}
await Promise.all(promises);
results.forEach(item => console.log(item))
}
async function asyncInLoopWithAwait() {
for (let i = 1; i <= 100; i++) {
try {
//Wait for getting response in every iteration
let word = await getRandomWord({ withErrors: true });
console.log(`${i}: ${word}`);
} catch (error) {
console.log(`${i}: Doh!`);
}
}
}
//asyncInLoopWithAwait()
asyncInLoopWithPromiseAllInOrder()
@philmander
Copy link

Good stuff. I hope you don't mind me suggesting a few more refinements...

Maintaining both results and promises arrays is a bit ugly and error prone for future maintainers. You can just do this:

async function two() {
    const promises = [];
    for (let i = 1; i <= 100; i++) {
        promises.push(
            getRandomWord({ withErrors: true })
                .then(value => `${i}: ${value}`)
                .catch(() => `${i}: Doh!`)
        );
    }
    const results = await Promise.all(promises);
    results.forEach(item => console.log(item))
}

It would be nice to use async/await completely, but an await will obviously block the loop. To circumvent this, we can use an async IIFE:

async function three() {
    const promises = [];
    for (let i = 1; i <= 100; i++) {
        promises.push((async () => {
            try {
                return `${i}: ${await getRandomWord({ withErrors: true })}`;
            } catch (err) {
                return `${i}: Doh!`;
            }
        })());
    }
    const results = await Promise.all(promises);
    results.forEach(item => console.log(item))
}

This does look a bit uglier though and ultimately (and usually in modern js), modifying a value from within a for loop is usually a code smell that it would be better in a more functional way. Here the code creates an empty array and maps it with the async function. Finally, it's also a bit nicer to join the printed results with a new line rather than iterating them again.

async function four() {
    const promises = Array(100).fill().map(async (v, i) => {
        try {
            return `${i + 1}: ${await getRandomWord({ withErrors: true })}`;
        } catch (err) {
            return `${i + 1}: Doh!`;
        }
    });
    const results = await Promise.all(promises);
    console.log(results.join('\n'));
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment