关于Promise的内存释放问题

Promise(fun_father)函数里包含了Promise(fun_son)函数,如果fun_father先resolve(),此时fun_son还没执行完,那么fun_son是会继续执行下去,还是终止?

let status= 0
const fun_father= () => {
    return new Promise((resolve, reject) => {
        fun_son().then(() => {
            status= 1
        })
        //例如请求之类的异步方法......
            resolve("fun_father done")
    }) 
}

const fun_son = () => {
    return new Promise((resolve ,reject) => {
        //例如请求之类的异步方法......
            resolve("fun_son done")
    })
}

fun_father().then(msg => {
    console.log(msg)
})

在写项目时碰到这种情况,简化后就是类似上面一样,我是希望能打印出"fun_father done",并且status也能改变为1。 这么写后,领导和我说如果fun_son执行得比fun_father快就没问题,但是如果反之,则会因为fun_father返回了,内存释放,fun_son就会终止执行。我对此还是有存疑的,但是自己试验的话没有好的测试异步方法(循环没用),setTimeout 是可以的,但不能完全说明。所以想请教大佬们,这样的写法是否可行。

阅读 6.5k
9 个回答

首先,Promise的作用是控制异步流程,如果你想要保证打印fun_father done的时候status一定置为1,那么你可以写成这样:

let status= 0
const fun_father= () => {
    return new Promise((resolve, reject) => {
        fun_son().then(() => {
            status= 1
        }).then(() => {
            //例如请求之类的异步方法......
            resolve("fun_father done")
        })
    }) 
}

const fun_son = () => {
    return new Promise((resolve ,reject) => {
        //例如请求之类的异步方法......
        resolve("fun_son done")
    })
}

fun_father().then(msg => {
    console.log(msg)
})

接下来,让我们来分析下楼主写法的执行栈

  • 首先执行fun_father函数,生成Promise中的函数会立即执行
  • 同理fun_son中生成Promise的函数会立即执行,此时fun_son中的异步方法加入异步事件队列,我们可以称作为fun_son_async
  • 代码会继续向下执行fun_father中的异步方法并加入异步事件队列,我们可以称作为fun_father_async
  • 此时就有两个没有流程控制的异步事件,输出的结果顺序也就不确定了

示例代码(可以在浏览器执行查看结果)

fun_father_async先返回,输出fun_father done但status为0

let status = 0;
const fun_father = () => {
  return new Promise((resolve, reject) => {
    fun_son().then(() => {
      status = 1;
      console.log('fun_son status==>>', status)
    });
    //例如请求之类的异步方法......
    setTimeout(() => resolve('fun_father done'), 1000);
  });
};

const fun_son = () => {
  return new Promise((resolve, reject) => {
    //例如请求之类的异步方法......
    setTimeout(() => {
        console.log('fun_son done')
        resolve('fun_son done')
    }, 2000);
  });
};

fun_father().then(msg => {
  console.log('fun_father status==>>', status);
  console.log(msg);
});

clipboard.png

这里可以看到,fun_father_async先返回了,并不会终止fun_son_async及之后的执行

fun_son_async先返回,输出fun_father done但status为1

let status = 0;
const fun_father = () => {
  return new Promise((resolve, reject) => {
    fun_son().then(() => {
      status = 1;
      console.log('fun_son status==>>', status)
    });
    //例如请求之类的异步方法......
    setTimeout(() => resolve('fun_father done'), 2000);
  });
};

const fun_son = () => {
  return new Promise((resolve, reject) => {
    //例如请求之类的异步方法......
    setTimeout(() => {
        console.log('fun_son done')
        resolve('fun_son done')
    }, 1000);
  });
};

fun_father().then(msg => {
  console.log('fun_father status==>>', status);
  console.log(msg);
});

clipboard.png

更好的写法

既然用了Promise做异步流程控制,其实一个链式调用就可以了

let status= 0
const fun_father= () => {
    //例如请求之类的异步方法......
}

const fun_son = () => {
    //例如请求之类的异步方法......
}

Promise.resolve()
    .then(fun_son)
    .then(() => status = 1)
    .then(fun_father)
    .then(() => console.log(msg))

附录

代码没有问题啊

按你现在的代码 fun_son 会继续执行;


补充:
你领导的意思是你这样写代码不太好, 如果fun_father resolve 后立马就要使用 status, 就会有不确定性.
可以稍微改一下 fun_father 的代码:

const fun_father= () => {
    let son = fun_son().then(() => {
            status= 1
        })
    let father = new Promise((resolve, reject) => {
        //例如请求之类的异步方法......
            
    });
    return Promise.all([son,father]).then(()=>{
        return "fun_father done";
    })
}

不论谁快,只要不出错的话,都会打印fun_father done,status都会为1

fun_son始终都会执行, 它已经放入了event loop

你領導可能不習慣gc語言

promise嵌套时,是按照由里向外依次执行的,

所以你为什么不把resolve("fun_father done")这段代码写到son里面呢?为什么要和son这个promise同级?

建议你再研究一下promise。

补充一下,promise是异步的,他会把resolve的结果推到微任务队列中等待处理,这个和垃圾回收机制没关系,你领导也是一知半解。

js层面哪有什么释放不释放的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏