为何初始化应用时Promise未等待依赖Promise完成就立即执行resolve/reject?
问题根源分析与修复方案
我一眼就看到了代码里几个典型的Promise使用误区,正是这些问题导致initApp的回调链完全不执行,咱们一步步拆解解决:
1. getData函数的冗余封装与错误的resolve/reject调用
你在getData里手动新建了一个Promise,但其实Promise.all本身就会返回一个Promise,这属于Promise反模式——完全没必要额外封装一层。更严重的是,你在then和catch里写的是return resolve和return reject,这完全不对:resolve和reject是需要调用的函数,不是要返回的值。
修复后的getData应该是这样:
function getData(promises, callback) { return Promise.all(promises) .then(function () { if (callback && typeof callback === "function") { debug_log("getData: running callback"); callback(); } // 无需手动resolve,Promise.all的then会自动传递成功状态 }) .catch(function (error) { debug_log("getData failed:", error); // 抛出错误让上层Promise捕获失败状态 throw error; }); }
- 直接返回
Promise.all的链式调用结果,省去多余的Promise构造 then里不需要手动调用resolve,因为Promise.all成功后,then的返回值会自动成为新Promise的resolved值catch里抛出错误,确保上层能捕获到失败状态
2. initApp的逻辑错误:没有等待异步操作,错误判断Promise状态
你在initApp里的逻辑完全走偏了:
dataReturned是getData返回的Promise对象,而resolve是Promise构造函数里的回调函数,两者永远不可能相等,所以代码会直接走到else分支- 更糟的是,你只是写了
resolve和reject,没有调用它们(应该是resolve()和reject(error)),不过即使调用了,逻辑也是错的——你根本没等待getData的异步操作完成
其实initApp根本不需要手动新建Promise,直接把getData的结果赋值给它就行,因为getData已经返回Promise了:
const initApp = getData([ getPartners, getProducts, getCurrencies, getSites ]);
如果一定要手动封装(比如需要额外的状态处理),那应该在Promise里等待getData的结果:
const initApp = new Promise((resolve, reject) => { getData([ getPartners, getProducts, getCurrencies, getSites ]) .then(() => { debug_log("resolve initapp"); resolve(); // 调用resolve函数,标记Promise为resolved }) .catch((error) => { debug_log("reject initapp"); reject(error); // 调用reject函数,传递错误信息 }); });
3. 最终修复后的完整调用链
现在你的initApp的then回调链就能正常执行了,因为Promise状态会正确等待getData的异步操作完成:
initApp .then(() => { initJSComponents(); }) .catch((error) => { debug_log("Problem during js component initialisation.", error); }) .then(() => { initDOM(); }) .then(function () { //some more stuff here }) .catch((error) => { debug_log("Problem during initialisation.", error); });
额外提示
- 尽量避免手动创建Promise(除非你要封装非Promise的异步操作),利用现有Promise的链式调用更简洁且不易出错
- 永远记住:
resolve和reject是函数,必须调用才会改变Promise的状态 Promise.all会等待所有传入的Promise都成功才进入then,只要有一个失败就会进入catch,这完全符合你“确保操作顺序/加载完成”的需求
内容的提问来源于stack exchange,提问作者ashkyn
相关产品推荐
相关产品推荐

