今天遇到一个业务,在递归函数中使用promise来确保程序的同步执行,但写的时候发现promise似乎失效了,我搞了很久才发现问题,而且是非常低级的问题,为了说明情况,我简化问题如下。
// 建立一个定时100ms的函数task1
function task1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 100)
})
}
// 建立一个递归函数aa,当num=20时,退出递归
async function aa(num) {
return new Promise(async (resolve)=>{
await task1()
if(num<20){
aa(++num)
}else{
console.log("aa_finish")
resolve();
}
})
}
// 建立一个函数bb来调用递归aa
async function bb(){
console.log("bb_start")
await aa(0);
console.log("bb_finish")
}
// 执行函数bb
bb();
正常来说,执行函数bb,函数aa递归20次后,浏览器打印信息的顺序是:bb_start、aa_finish、bb_finish
但事与愿违,输出结果如下:
结果并没有出现"bb_finish"
我想,不应该啊,不是写了resolve()了吗?函数在await之后应该会继续执行的。
后面发现,我太蠢了,这个resolve()是第20次递归后的resolve(),函数bb要的是第一次的resolve(),所以我们可以创建一个变量来保存第一次的resolve()。修改后如下:
// 创建变量cc用来保存resolve
let cc;
function task1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 100)
})
}
async function aa(num) {
return new Promise(async (resolve)=>{
// 保存第一次的resolve
if(num==0){
cc=resolve;
}
await task1()
if(num<20){
aa(++num)
}else{
console.log("aa_finish")
// 执行第一次的resolve,即保存在变量cc中resolve
cc();
}
})
}
async function bb(){
console.log("bb_start")
await aa(0);
console.log("bb_finish")
}
bb();
可以看到,结果正常运行了。