JS Promise链中数组存在元素但打印length始终为0问题咨询
问题原因
这是典型的异步任务执行时序问题,核心原因如下:
- 你在第一个
then的循环中调用的Xrm.WebApi.online.retrieveRecord本身是异步接口,调用后不会立刻执行成功回调,而是会进入异步队列等待执行。 - 你在循环结束后直接同步
return flightName,此时所有的retrieveRecord请求还没有返回结果,success回调都没被触发,flightName自然还是空数组,所以第二个then里打印length就会得到0。 - 控制台打印数组对象时,浏览器输出的是数组的引用,等你手动在控制台展开数组时,异步请求已经返回、数组已经被填充了新元素,所以你能看到长度为2的内容,和你截图的效果一致,这属于浏览器控制台的特殊展示特性,不是代码运行时序的真实反映。

修复方案
你需要把所有retrieveRecord生成的Promise也收集起来,再用Promise.all等待全部执行完成后再返回结果,修正后的代码如下:
let guidArr = []; Promise.all(guidArr) .then(values => { // 收集所有检索请求的Promise const retrievePromises = values.map(guid => { return Xrm.WebApi .online .retrieveRecord("crd80_flightplanevent", guid, "?$select=_crd80_learnerflight_value") .then( function success(result) { // 直接返回目标值,无需额外定义全局数组存储 return result["_crd80_learnerflight_value@OData.Community.Display.V1.FormattedValue"] }, function(error) { DisplayError(error) // 出错时可根据业务需求返回空值,或者抛出错误终止执行 return null }); }) // 等待所有检索请求执行完成,返回结果组成的数组 return Promise.all(retrievePromises) }).then(flightName => { // 可选:过滤掉出错返回的空值 flightName = flightName.filter(Boolean) console.log(flightName) console.log(flightName.length) // 此处拿到的flightName已经是全部请求完成后的最终结果,可直接操作每一项 return flightName })
- 修正后不需要再提前定义全局的
flightName数组,所有结果会在异步请求全部完成后统一汇总,此时拿到的数组长度和内容都是实时准确的,可直接进行后续处理。
内容的提问来源于stack exchange,提问作者Martin Hutchins
相关产品推荐
相关产品推荐

