我正在实现一个Generator函数,它使用for循环遍历给定的数字范围并找到主要数字。
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
}
}
}
为每个素数调用Promise并检索其名称(例如,当给定3将返回'3'时)。
我的问题是为什么当给出数字2并抛出错误时,在解析的数据之后记录消息。我的目标是在请求号码时记录它。
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))
}
}
结果是
three
five
seven
The requested number 2 is not found!
提前谢谢!
答案 0 :(得分:1)
您正在立即创建所有承诺,因此未确定分辨率顺序。为了强制执行它,你需要用类似的东西链接它们:
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) )
}
哪个输出:
The requested number 2 is not found!
three
five
seven
修改:使用async
如果你不喜欢递归,你可以使用异步函数(我假设你可以使用它,因为你已经使用了生成器)。作为奖励,我使用for of
循环使您的代码更具可读性:
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)
}
}
}