while 循环如何与 Nodejs 中的 promise 和回调函数一起使用?
How the while loop works with promise and callback function in Nodejs?
这是我第一次用Promise和回调编写while循环。我不知道为什么会导致死循环。如何解决?
async function getResult(){
return new Promise((resolve, reject) => {
let params ="some input and setting";
let next = "hasNext";
let array = [];
let error = null;
while(next !== null){
checkNext(params, function(err,data) { //checkNext is a function to return the current list and check wether there has the next list
if(err){
next = null;
error = err;
}else{
next = data.hasNext; // if there is not next list, data.hasNext = null
array = array.concat(data.array); // data.array return the current list
}
});
}
if(error !== null){
reject(error);
}else{
resolve(array); // I want to return all lists
}
});
}
它会导致无限循环,因为 checkNext()
是异步和非阻塞的,所以你的 while()
会永远运行,甚至在对 checkNext()
的一次调用有机会完成并调用之前它的回调。
你永远不会使用 while()
循环等待 Javasacript 中的一些异步事情完成(除了 await
如下所示)因为在 nodejs 的事件驱动架构中,while 循环从不 returns 将控制权交还给事件循环,因此没有异步操作永远无法处理其完成事件,因此您正在等待的事情永远不会有机会发生。如果您使用 await
等待连接到您的异步事件的承诺,情况会有所不同(如下所示)。然后,你可以成功地使用一个while()
循环。
对于要使用 promises 的异步操作,您几乎总是希望对异步操作进行 promisify,以便所有控制流都带有 promises,而不是简单的回调,因为两者不能很好地混合。这就是我的建议:
const { promisify } = require('util');
const checkNextP = promisify(checkNext);
async function getResult() {
let params = "some input and setting";
let next = "hasNext";
let array = [];
while (next !== null) {
let data = await checkNextP(params);
next = data.hasNext; // if there is not next list, data.hasNext = null
array = array.concat(data.array); // data.array return the current list
}
return array;
}
在这里,while
循环起作用是因为我们使用 await
并承诺 return 来自 checkNextP()
并且 await
暂停执行函数直到那个承诺 resolves/rejects.
关于异步函数如何工作的更多解释
当我们点击第一个 await
时,此 async
函数将自动 return 一个承诺。调用者将在此时得到该承诺。然后,当第一个 await
的承诺解决时,该函数将恢复,您将获得第一个 data
值,然后执行循环的其余部分。此过程将重复,直到 next
为 null
。到那时,您的 while()
循环将完成并且 return array
语句将执行。因为这是一个 async
函数,所以 return 语句真正做的是它解决了 async
函数先前 returned 的承诺,并将 array
设置为是该承诺的解决值。
如果来自 checkNextP()
的承诺被拒绝,那么 await checkNextP()
将抛出拒绝,并且由于我们没有围绕它的 try/catch
,async
函数将自动捕获该抛出并且它将拒绝 async
函数先前已 returned 的承诺,导致调用者得到承诺拒绝,无论 checkNextP()
拒绝什么错误。所以,这里的错误处理也是有效的。
getResult()
的调用者,只需要做这样的事情:
getResult().then(results => {
console.log(results);
}).catch(err => {
console.log(err);
});
或者,调用者也可以在 async
函数本身中并使用 await
和 try/catch
来捕获错误。
这是我第一次用Promise和回调编写while循环。我不知道为什么会导致死循环。如何解决?
async function getResult(){
return new Promise((resolve, reject) => {
let params ="some input and setting";
let next = "hasNext";
let array = [];
let error = null;
while(next !== null){
checkNext(params, function(err,data) { //checkNext is a function to return the current list and check wether there has the next list
if(err){
next = null;
error = err;
}else{
next = data.hasNext; // if there is not next list, data.hasNext = null
array = array.concat(data.array); // data.array return the current list
}
});
}
if(error !== null){
reject(error);
}else{
resolve(array); // I want to return all lists
}
});
}
它会导致无限循环,因为 checkNext()
是异步和非阻塞的,所以你的 while()
会永远运行,甚至在对 checkNext()
的一次调用有机会完成并调用之前它的回调。
你永远不会使用 while()
循环等待 Javasacript 中的一些异步事情完成(除了 await
如下所示)因为在 nodejs 的事件驱动架构中,while 循环从不 returns 将控制权交还给事件循环,因此没有异步操作永远无法处理其完成事件,因此您正在等待的事情永远不会有机会发生。如果您使用 await
等待连接到您的异步事件的承诺,情况会有所不同(如下所示)。然后,你可以成功地使用一个while()
循环。
对于要使用 promises 的异步操作,您几乎总是希望对异步操作进行 promisify,以便所有控制流都带有 promises,而不是简单的回调,因为两者不能很好地混合。这就是我的建议:
const { promisify } = require('util');
const checkNextP = promisify(checkNext);
async function getResult() {
let params = "some input and setting";
let next = "hasNext";
let array = [];
while (next !== null) {
let data = await checkNextP(params);
next = data.hasNext; // if there is not next list, data.hasNext = null
array = array.concat(data.array); // data.array return the current list
}
return array;
}
在这里,while
循环起作用是因为我们使用 await
并承诺 return 来自 checkNextP()
并且 await
暂停执行函数直到那个承诺 resolves/rejects.
关于异步函数如何工作的更多解释
当我们点击第一个 await
时,此 async
函数将自动 return 一个承诺。调用者将在此时得到该承诺。然后,当第一个 await
的承诺解决时,该函数将恢复,您将获得第一个 data
值,然后执行循环的其余部分。此过程将重复,直到 next
为 null
。到那时,您的 while()
循环将完成并且 return array
语句将执行。因为这是一个 async
函数,所以 return 语句真正做的是它解决了 async
函数先前 returned 的承诺,并将 array
设置为是该承诺的解决值。
如果来自 checkNextP()
的承诺被拒绝,那么 await checkNextP()
将抛出拒绝,并且由于我们没有围绕它的 try/catch
,async
函数将自动捕获该抛出并且它将拒绝 async
函数先前已 returned 的承诺,导致调用者得到承诺拒绝,无论 checkNextP()
拒绝什么错误。所以,这里的错误处理也是有效的。
getResult()
的调用者,只需要做这样的事情:
getResult().then(results => {
console.log(results);
}).catch(err => {
console.log(err);
});
或者,调用者也可以在 async
函数本身中并使用 await
和 try/catch
来捕获错误。