I'm implementing a Generator function that uses a for loop to go through given range of numbers and find the prime ones.
function * findPrimeNumbers (from, to) {
for (let i = from; i <= to; i++) {
let isCurrentNumber = true
for (let j = 2; j < i; j++) {
if (i % j === 0) {
isCurrentNumber = false
break
}
}
if (isCurrentNumber) {
yield i
}
}
}
A Promise is called for each prime number and retrieves its name (e.g. when given 3 will return 'three').
My question is why when the number 2 is given and the error is thrown, the message is logged after the resolved ones. My goal is to log it when the number is question is requested.
const data = [
{
id: 5,
name: 'five'
},
{
id: 7,
name: 'seven'
},
{
id: 3,
name: 'three'
},
// Two is a prime number and it will not be found.
// The error message will come after the resolved ones although it is the first number to be requested.
// Why?
// {
// id: 2,
// name: 'two'
// }
]
function getNumberName (primeNumber, numbers) {
return new Promise((resolve, reject) => {
const retrievedNumber = numbers.find(number => number.id === primeNumber)
if (retrievedNumber) {
resolve(retrievedNumber.name)
} else {
reject(new Error(`The requested number ${primeNumber} is not found!`))
}
})
}
const result = findPrimeNumbers(2, 10) // start executing the generator
let isDone = false
while (!isDone) {
let current = result.next()
isDone = current.done
if (!isDone) {
let numberName = getNumberName(current.value, data)
numberName
.then(name => console.log(name))
.catch(error => console.log(error.message))
}
}
The result is
three
five
seven
The requested number 2 is not found!
Thank you in advance!
You are creating all the promise at once, so the resolution order is not determined. In order to enforce it you'll need to chain them with something like that:
const result = findPrimeNumbers(2, 10); // start executing the generator
checkNextNumber(result)
function checkNextNumber(result) {
let current = result.next();
if(current.done) return;
let numberName = getNumberName(current.value, data);
numberName
.then(name => console.log(name))
.catch(error => console.log(error.message))
.then( () => checkNextNumber(result) )
}
Which outputs:
The requested number 2 is not found!
three
five
seven
Edit: Use async
If you don't like recursion, you can use an async function (which I assume you can use as you are already using generator anyway). As a bonus, I use a for of
loop that makes your code more readable:
async function checkNextNumberAsync(result) {
for(let current of result) {
try {
let name = await getNumberName(current, data);
console.log(name);
} catch(e) {
console.log(e.message)
}
}
}