当单个承诺解决或拒绝时,如何让我的程序保持 运行?
How do I get my program to keep running when a single promise resolves or rejects?
如果一切正常,我希望我的程序能够解决问题,然后使用 for 循环进行下一个测试;或者,如果出现错误,我希望它再次 运行。但是如果它遇到六次错误,我希望它放弃并尝试循环的下一个函数。
我的期望:
index is 0 and loop is 0
index is 1 and loop is 0
index is 2 and loop is 0
index is 3 and loop is 0
index is 4 and loop is 0
index is 5 and loop is 0
5 is too many errors
[printed error]
index is 0 and loop is 7
index is 1 and loop is 7
index is 2 and loop is 7
index is 3 and loop is 7
index is 4 and loop is 7
index is 5 and loop is 7
5 is too many errors
[printed error] .. and so on
我实际得到的是:
index is 0 and loop is 0
index is 1 and loop is 0
index is 2 and loop is 0
index is 3 and loop is 0
index is 4 and loop is 0
index is 5 and loop is 0
5 is too many errors
(node:29808) UnhandledPromiseRejectionWarning: undefined
(node:29808) UnhandledPromiseRejectionWarning: Unhandled promise rejection.
代码:
const hello = async (index, i) => {
return new Promise(async (resolve, reject) => {
console.log(`index is ${index} and loop is ${i}`)
if(index === 5){
reject(console.log(`${index} is too many errors`)) // this runs
} else if (index === 6){
resolve(console.log("I realize it won't ever resolve :) "))
}
else{
hello(++index, i)
}
})
};
const loop_function = async () => {
return new Promise (async(res, rej)=>{
for (var i = 0; i <= 35; i += 7) {
try{
await hello(0, i)
} catch(err){
console.log("caught an error!") // this does not run
}
}
res(console.log("resolved everything")) // this does not run
})
}
const final = async () =>{
await loop_function()
console.log("loop_function complete") // this does not run
}
final();
问题是您的递归 hello(++index, i)
调用被忽略了——您从不使用它的结果值。它可能是一个被拒绝的承诺(然后你会收到 "unhandled rejection" 警告),更糟糕的是,你永远不会解决你正在构建的承诺。但是你应该避免 Promise
constructor antipattern 无论如何!
async function hello(index, i) {
console.log(`index is ${index} and loop is ${i}`)
if (index === 5) {
throw new Error(`${index} is too many errors`)
} else if (index === 6) {
return "I realize it won't ever resolve :)"
} else {
return hello(++index, i)
// ^^^^^^ this is essential! Or at least `await` the returned promise
}
}
async function loop() {
for (var i = 0; i <= 35; i += 7) {
try {
await hello(0, i)
} catch(err) {
console.log("caught an error!", err)
}
}
console.log("resolved everything")
}
loop().then(() => {
console.log("loop_function complete")
}, () => {
console.log("unhandled error")
})
要修改的内容:
- 从两个函数中清除
new Promise()
包装器;它们是不必要的,因为 AsyncFunctions 保证 return Promise 并且在内部你可以简单地 return/throw.
- 一定要
return hello(++index, i)
以便return递归的每一层的结果到它的上层,并最终到达最顶层的原始调用者。
- 当满足
(index >= 5)
条件时,直接抛出一个Error;不需要记录,因为调用者的(loop_function 的)catch
块将进行记录。
所以,你可能会得到:
const hello = async (index, i) => {
console.log(`index is ${index} and loop is ${i}`);
if(index >= 5) {
throw new Error(`${index} is too many errors`);
} else {
return hello(++index, i);
}
};
const loop_function = async () => {
for (var i = 0; i <= 35; i += 7) {
try {
await hello(0, i);
} catch(err) {
console.log(err.message);
}
}
console.log("resolved everything");
}
const final = async () =>{
await loop_function();
console.log("loop_function complete");
}
final();
如果一切正常,我希望我的程序能够解决问题,然后使用 for 循环进行下一个测试;或者,如果出现错误,我希望它再次 运行。但是如果它遇到六次错误,我希望它放弃并尝试循环的下一个函数。
我的期望:
index is 0 and loop is 0
index is 1 and loop is 0
index is 2 and loop is 0
index is 3 and loop is 0
index is 4 and loop is 0
index is 5 and loop is 0
5 is too many errors
[printed error]
index is 0 and loop is 7
index is 1 and loop is 7
index is 2 and loop is 7
index is 3 and loop is 7
index is 4 and loop is 7
index is 5 and loop is 7
5 is too many errors
[printed error] .. and so on
我实际得到的是:
index is 0 and loop is 0
index is 1 and loop is 0
index is 2 and loop is 0
index is 3 and loop is 0
index is 4 and loop is 0
index is 5 and loop is 0
5 is too many errors
(node:29808) UnhandledPromiseRejectionWarning: undefined
(node:29808) UnhandledPromiseRejectionWarning: Unhandled promise rejection.
代码:
const hello = async (index, i) => {
return new Promise(async (resolve, reject) => {
console.log(`index is ${index} and loop is ${i}`)
if(index === 5){
reject(console.log(`${index} is too many errors`)) // this runs
} else if (index === 6){
resolve(console.log("I realize it won't ever resolve :) "))
}
else{
hello(++index, i)
}
})
};
const loop_function = async () => {
return new Promise (async(res, rej)=>{
for (var i = 0; i <= 35; i += 7) {
try{
await hello(0, i)
} catch(err){
console.log("caught an error!") // this does not run
}
}
res(console.log("resolved everything")) // this does not run
})
}
const final = async () =>{
await loop_function()
console.log("loop_function complete") // this does not run
}
final();
问题是您的递归 hello(++index, i)
调用被忽略了——您从不使用它的结果值。它可能是一个被拒绝的承诺(然后你会收到 "unhandled rejection" 警告),更糟糕的是,你永远不会解决你正在构建的承诺。但是你应该避免 Promise
constructor antipattern 无论如何!
async function hello(index, i) {
console.log(`index is ${index} and loop is ${i}`)
if (index === 5) {
throw new Error(`${index} is too many errors`)
} else if (index === 6) {
return "I realize it won't ever resolve :)"
} else {
return hello(++index, i)
// ^^^^^^ this is essential! Or at least `await` the returned promise
}
}
async function loop() {
for (var i = 0; i <= 35; i += 7) {
try {
await hello(0, i)
} catch(err) {
console.log("caught an error!", err)
}
}
console.log("resolved everything")
}
loop().then(() => {
console.log("loop_function complete")
}, () => {
console.log("unhandled error")
})
要修改的内容:
- 从两个函数中清除
new Promise()
包装器;它们是不必要的,因为 AsyncFunctions 保证 return Promise 并且在内部你可以简单地 return/throw. - 一定要
return hello(++index, i)
以便return递归的每一层的结果到它的上层,并最终到达最顶层的原始调用者。 - 当满足
(index >= 5)
条件时,直接抛出一个Error;不需要记录,因为调用者的(loop_function 的)catch
块将进行记录。
所以,你可能会得到:
const hello = async (index, i) => {
console.log(`index is ${index} and loop is ${i}`);
if(index >= 5) {
throw new Error(`${index} is too many errors`);
} else {
return hello(++index, i);
}
};
const loop_function = async () => {
for (var i = 0; i <= 35; i += 7) {
try {
await hello(0, i);
} catch(err) {
console.log(err.message);
}
}
console.log("resolved everything");
}
const final = async () =>{
await loop_function();
console.log("loop_function complete");
}
final();