JavaScript中如何在不直接调用函数的情况下等待其执行完成
问题与解决方案
问题
我有多个互相异步调用的函数,需要捕获最后一个函数(Last)执行完成的时机。但如果在每个调用中使用Promise会导致调用方等待,而我需要调用方继续执行现有同步逻辑。现有代码及期望输出如下:
现有代码
function First(){ console.log('First is called'); setTimeout(Second, 1000); console.log('First fired Second and does not wait for its execution'); return; } function Second(){ console.log('Second is called'); setTimeout(Last, 1000); } function Last(){ console.log('Last is called'); } function Main(){ First(); // 需要等待Last执行完成后再执行此行 console.log('called First and continue only after Last is done'); }
期望日志输出
First is called First fired Second and does not wait for its execution // 等待1秒 Second is called // 再等待1秒 Last is called called First and continue only after Last is done
解决方案
方案一:回调函数传递
通过给异步函数传递回调,在最后一个函数执行完成时触发回调,实现后续逻辑的延迟执行,同时不阻塞调用方的同步代码:
function First(callback){ console.log('First is called'); setTimeout(() => Second(callback), 1000); console.log('First fired Second and does not wait for its execution'); } function Second(callback){ console.log('Second is called'); setTimeout(() => Last(callback), 1000); } function Last(callback){ console.log('Last is called'); callback?.(); // 触发回调通知完成 } function Main(){ First(() => { console.log('called First and continue only after Last is done'); }); } Main();
方案二:Promise封装异步链
用Promise封装整个异步调用链,调用方通过.then()监听完成事件,同步代码不受阻塞:
function First(){ console.log('First is called'); const asyncPromise = new Promise(resolve => { setTimeout(() => Second(resolve), 1000); }); console.log('First fired Second and does not wait for its execution'); return asyncPromise; } function Second(resolve){ console.log('Second is called'); setTimeout(() => Last(resolve), 1000); } function Last(resolve){ console.log('Last is called'); resolve(); } function Main(){ const chainPromise = First(); // 此处可添加其他同步逻辑,会立即执行 chainPromise.then(() => { console.log('called First and continue only after Last is done'); }); } Main();
两种方案都能满足需求:First的同步代码会立即执行,不会被异步逻辑阻塞,同时后续指定的代码会在Last执行完成后才触发。
内容的提问来源于stack exchange,提问作者Dmitry Klavdiev
相关产品推荐
相关产品推荐

