fetch promise加载器无结果?makeQueryablePromise值为undefined
可查询Promise封装中的值异常问题
在对应的Codesandbox示例中,代码会将近20个由fetch生成的promise存入数组,通过进度条跟踪这些promise的完成状态。
核心疑问
为什么在makeQueryablePromise中执行console.log('inside makeQueryablePromise ', value);时,打印出的value为undefined;但在fetch的后续处理逻辑中执行console.log('inside fetch ', data)时,却能拿到正常的返回数据——makeQueryablePromise持有的明明是同一个promise实例?
实际运行的日志截图


问题根因解析
这个现象和Promise的执行时序特性直接相关,不存在实例不匹配的问题:
makeQueryablePromise的封装逻辑是同步执行的。当你调用这个方法去包裹fetch生成的Promise时,整个fetch请求还处于网络等待的pending状态,此时原生Promise内部根本还没有写入返回值,默认值就是undefined。你在封装方法里写的console.log是同步代码,执行的时候根本等不到网络请求返回,自然打印出来是undefined。- 你写在fetch链路里的
console.log('inside fetch ', data)是挂载在.then()回调里的,这部分代码属于微任务,只会在网络请求完成、Promise状态正式变更为fulfilled之后才会被执行,此时异步流程已经走完,自然能拿到完整的返回数据。
可以用最简代码复现这个时序差:
const p = new Promise((resolve) => { // 模拟1秒的网络请求 setTimeout(() => resolve('正常返回的接口数据'), 1000) }) // 同步执行:此时p还在pending状态,内部无值,打印undefined console.log('同步读取p的值:', p.__internalValue) // 异步回调:等p状态变更后执行,能拿到完整数据 p.then(data => console.log('then回调拿到的值:', data))
很多人对可查询Promise封装存在误解:以为封装完可以同步读到最终的接口返回值。实际上即便你在封装方法里给原Promise挂载.then()来把返回值赋值到自身的value属性上,这个赋值动作依然是异步执行的,在同步代码中读取永远是初始值undefined,必须等微任务队列执行完成之后,value才会被填充为真实数据。
内容的提问来源于stack exchange,提问作者Kid
相关产品推荐
相关产品推荐

