为何Promise中console.log与.then()的使用位置会影响执行结果?
我在练习Promise概念时遇到一个问题:用Promise和回调函数实现相同逻辑,却得到不同结果。困惑点在于:Promise场景中console.log和return的位置会影响执行结果,但回调函数场景不会;只有把console.log放在.then()的回调里,才能得到和回调场景一致的结果,想知道原因。
测试代码
Promise方式1
let sample = new Promise((success) => { return success(3); }); console.log(sample.then((x) => { return x; })) // result:promise object
回调函数方式
function sample(callbackP) { return callbackP(3) } function callback(x) { return x; } console.log(sample(callback)); //result:3
Promise方式2
let sample = new Promise((success) => { console.log(success(3)); }); sample.then((x) => { return x; }) // result:nothing
Promise方式3(正确结果)
let sample = new Promise((success) => { success(3); }); sample.then((x) => { console.log(x); }) // result:3
原因解析
核心差异:同步回调 vs 异步Promise
回调函数是同步执行的:调用sample(callback)时,会直接执行callbackP(3)并返回结果,所以console.log能直接拿到3。
而Promise的核心是异步任务管理——哪怕Promise内部同步调用success(3),.then()的回调也会被放入微任务队列,等当前所有同步代码执行完毕后才会触发,这是两者行为差异的根本原因。
逐个分析测试代码
Promise方式1:打印的是Promise实例
sample.then()的返回值永远是一个新的Promise对象,不管你在回调里return什么值。你直接打印这个返回的Promise实例,自然输出的是Promise对象,而非回调里的x。回调函数方式:同步返回结果
sample(callback)调用后直接执行callback(3),同步返回3,console.log直接获取到这个值,所以输出3。Promise方式2:打印的是resolve函数的返回值
success()(即Promise的resolve函数)的返回值是undefined,你在这里console.log的是这个undefined;而.then()的回调里没有打印操作,所以最终看不到3。Promise方式3:正确利用异步回调
success(3)将Promise标记为已完成状态,.then()的回调会在当前同步代码执行完后,从微任务队列取出执行,此时x拿到3,console.log输出正确结果。
内容的提问来源于stack exchange,提问作者teo77

