数组存入REST返回对象后length仍为0的技术问题求助
问题排查:REST请求数据推入数组后length为0但控制台可见元素
我通过REST请求获取对象并推入数组,控制台打印数组能看到元素,但调用length属性时返回0。已搜索相关资料未找到解决方案,附上相关代码,请求帮助排查问题。
相关代码
private getArkiv(): void { const currentUser = this.context.pageContext.user.email const requestUrl = `https://johannawl.sharepoint.com/sites/Maintainance/_api/web/lists/getbytitle('Arkivlista')/items?$select=ID,libGuid,PageType,Site,Owner/Title,Owner/EMail&$expand=Owner&$filter=Owner/EMail%20eq%20%27${currentUser}%27%20and%20PageType%20eq%20%27Scenkonst%27` let siteUrl: string; let LibGuid: string; const fileArr: {FileLeafRef: string; href: string; Id: string; isArchived: boolean;}[] = []; this.getItemsRest(requestUrl).then(data => { for (let i = 0; i < data.value.length; i++) { const item = data.value[i]; siteUrl = item.Site.Url; LibGuid = item.libGuid; const requestUri = `${siteUrl}/_api/web/lists/getbyid('${LibGuid}')/items?$select=Title,ID,FileRef,FileLeafRef,attention&$filter=attention%20eq%20%271%27` this.getFilesRest(requestUri).then(data => { for (let j = 0; j < data.value.length; j++) { const fileItem = data.value[j]; const file = this.addFile(fileItem); fileArr.push(file); console.log('jw fileItem: ', fileItem) } }) } this.processData(fileArr) console.log("jw fileArr: ", fileArr); console.log("jw length fileArr: ", fileArr.length); console.log("jw is array fileArr: ", Array.isArray(fileArr)); }) } private processData(data: any): void { let html: string = ""; let count: number = 0; let countst: string = ""; for (let i = 0; i < data.length; i++) { const file = data[i]; html += ` <tr> <td> <span><a href="${file.href}">${file.FileLeafRef}</a></span> </td> <td> <span>Test</span> </td> </tr> `; count++; countst = count.toString(); } $("#Alla").text(`Filer (${countst})`); document.getElementById("tbodyAlla").innerHTML = html; $("#table").DataTable({ responsive: true, destroy: true }) }
问题原因
这是异步操作的时序问题:
getFilesRest是异步请求,你在循环里发起请求后,没等这些请求返回结果,就直接执行了processData(fileArr)和打印length的代码。此时fileArr还没有被填充任何元素,所以length返回0。- 控制台打印的数组是引用类型,当后续异步请求完成、元素被推入数组后,控制台会自动更新显示这个引用的最新状态,所以你能看到元素,但此时length已经打印过了。
解决方案
用Promise.all收集所有getFilesRest的异步请求,等全部请求完成后再处理数组:
private getArkiv(): void { const currentUser = this.context.pageContext.user.email const requestUrl = `https://johannawl.sharepoint.com/sites/Maintainance/_api/web/lists/getbytitle('Arkivlista')/items?$select=ID,libGuid,PageType,Site,Owner/Title,Owner/EMail&$expand=Owner&$filter=Owner/EMail%20eq%20%27${currentUser}%27%20and%20PageType%20eq%20%27Scenkonst%27` const fileArr: {FileLeafRef: string; href: string; Id: string; isArchived: boolean;}[] = []; this.getItemsRest(requestUrl).then(async data => { // 收集所有异步请求的Promise const filePromises = data.value.map(item => { const siteUrl = item.Site.Url; const LibGuid = item.libGuid; const requestUri = `${siteUrl}/_api/web/lists/getbyid('${LibGuid}')/items?$select=Title,ID,FileRef,FileLeafRef,attention&$filter=attention%20eq%20%271%27` return this.getFilesRest(requestUri).then(fileData => { // 填充数组 fileData.value.forEach(fileItem => { const file = this.addFile(fileItem); fileArr.push(file); console.log('jw fileItem: ', fileItem) }) }) }) // 等待所有异步请求完成 await Promise.all(filePromises) // 此时数组已填充完毕,再处理数据 this.processData(fileArr) console.log("jw fileArr: ", fileArr); console.log("jw length fileArr: ", fileArr.length); console.log("jw is array fileArr: ", Array.isArray(fileArr)); }) }
修改说明:
- 用
map替代循环,把每个getFilesRest请求包装成Promise并收集到数组中 - 使用
await Promise.all(filePromises)等待所有请求完成,确保数组已经被填充 - 之后再执行
processData和打印操作,就能得到正确的数组长度和内容
内容的提问来源于stack exchange,提问作者Johanna Weidenius
相关产品推荐
相关产品推荐

