Promise链异常:.then()在Promise resolve前触发的问题排查
这个问题的核心是Promise链被意外中断了,导致后续代码没等异步操作完成就提前执行了,咱们一步步拆解来看:
问题出在哪?
看你的User.initiate方法代码:
initiate(API) { API.GET({授权检查接口地址}) .then(authData => this.regenerate(authData._embedded.user)); },
这个方法内部确实发起了异步的GET请求,但没有返回这个Promise链。当主Promise链执行到.then(() => User.initiate(API))时,这个回调函数的返回值是undefined(因为initiate没有return任何内容)。
根据Promise的规则:如果then的回调函数返回的不是Promise对象,JavaScript会自动把它包装成一个已resolved的Promise,值就是返回的内容(这里是undefined)。这就意味着,主链的下一个then(也就是打印User.name的那个)会立刻执行,完全不等initiate里的GET请求完成、User属性被填充。
这就是为什么你看到的执行顺序是:
POST done
GET start
wat
GET done
console.log在GET done之前就跑了,此时User.name还没被赋值,所以输出wat。
怎么修复?
只需要修改User.initiate方法,让它返回内部的Promise链,这样外部的Promise链就能正确等待这个异步操作完成:
initiate(API) { // 关键:return这个Promise,让主链能等待它完成 return API.GET({授权检查接口地址}) .then(authData => this.regenerate(authData._embedded.user)); },
另外,你的regenerate方法其实可以简化——因为它里面的Promise只是同步赋值后resolve,完全可以直接返回this(then会自动把它包装成resolved的Promise):
regenerate(userData) { this.name = userData.name; // 其他User属性同理 return this; // 直接返回当前实例,无需手动创建Promise }
修复后的执行顺序
修改后,整个流程会按照你的预期执行:
- 登录POST请求完成 →
POST done - 发起授权检查GET请求 →
GET start - GET请求完成 →
GET done User属性被填充,最后控制台打印User.name
内容的提问来源于stack exchange,提问作者EmilBogumil

