JavaScript中if语句无法识别setTimeout执行后的变量更新问题
问题原因:JavaScript异步任务与事件循环机制导致的变量判断问题
深层原因解释
核心问题出在JavaScript的事件循环(Event Loop)机制,以及同步任务和异步任务的执行顺序差异:
同步任务优先执行:
JavaScript引擎会先执行所有不需要等待的同步代码。你的两个if判断都是同步任务,代码加载后会立刻按顺序执行:- 第一个
if (isHome === false):此时isHome为初始值false,触发setTimeout调用,但setTimeout的回调是异步任务,会被放到任务队列里排队,不会立即执行。 - 紧接着执行第二个
if (isHome === true):这时候setTimeout的回调还没跑,isHome依然是false,所以greetMother不会被调用。
- 第一个
异步任务的执行时机:
只有当所有同步任务执行完毕、主线程空闲时,引擎才会从任务队列取出异步任务执行。2秒后comeHome才会被调用,此时isHome被设为true,但第二个if判断早就执行完了,自然不会触发greetMother。
不管是基础写法还是面向对象写法,本质逻辑完全一致,所以都会遇到同样的问题——异步任务修改变量的时机,晚于同步的条件判断。
修复方案
要让greetMother在isHome变为true后执行,需要把调用逻辑绑定到异步任务的执行流程中,以下是几种常见方案:
方案1:直接在comeHome中调用greetMother
let isHome = false; const comeHome = () => { isHome = true; console.log("Going home now"); greetMother(); // 回家后直接触发打招呼 }; const greetMother = () => { console.log("Hi Mom!"); }; if (isHome === false) { setTimeout(() => { comeHome(); }, 2000); }
方案2:用Promise封装异步逻辑(更灵活)
let isHome = false; const comeHome = () => { return new Promise(resolve => { setTimeout(() => { isHome = true; console.log("Going home now"); resolve(); }, 2000); }); }; const greetMother = () => { console.log("Hi Mom!"); }; if (isHome === false) { comeHome().then(greetMother); }
方案3:async/await写法(更直观)
let isHome = false; const comeHome = () => { return new Promise(resolve => { setTimeout(() => { isHome = true; console.log("Going home now"); resolve(); }, 2000); }); }; const greetMother = () => { console.log("Hi Mom!"); }; async function run() { if (isHome === false) { await comeHome(); greetMother(); } } run();
内容的提问来源于stack exchange,提问作者webdevnoob
相关产品推荐
相关产品推荐

