为什么async函数加载的文档数组打印长度为0但展开可见内容?
问题原因
- 异步执行逻辑问题:
async函数的执行是非阻塞的,你调用getArray()后,代码碰到内部的await getDocs会暂停函数内的执行,立刻返回控制权给主线程执行后续的console.log语句,此时异步请求还未返回,数组还未被填充,因此打印的length为 0。
你直接打印数组能看到完整内容,是浏览器控制台的懒求值特性导致的:控制台打印引用类型(数组、对象)时,只会保存引用指针,当你手动点击展开对象时,才会读取当前内存中该引用的实际值,此时异步请求已经完成,数组已经被填充,所以能看到完整元素。
- 代码笔误:你定义的数组变量名为
array,但循环赋值时用的是未定义的arrayList,即使异步逻辑正确也无法正确填充值。
修复方案
- 第一步:修正变量名错误,将循环内的
arrayList替换为array - 第二步:等待异步函数执行完成后再访问数组内容,两种常用实现方式如下:
方式1:在async作用域内用await等待执行完成
方式2:用const array = []; async function getArray() { const arraySnaps = await getDocs(collection(db, "CollectionName")); for(var i = 0; i < arraySnaps.docs.length; i++){ // 修正变量名 array[i] = arraySnaps.docs[i].data(); } return array; } // 用自执行async函数包裹,等待异步执行完成后再访问数组 (async () => { await getArray(); // 此时数组已经填充完成,可以正常使用 console.log(array.length); console.log(array); // 所有需要使用该数组的逻辑都要放在这个作用域内 })().then()回调处理异步结果(更推荐无全局变量的写法,避免变量污染)async function getArray() { const arraySnaps = await getDocs(collection(db, "CollectionName")); // 直接用map生成目标数组返回,无需依赖外部全局变量 return arraySnaps.docs.map(doc => doc.data()); } getArray().then(array => { // 回调内可以直接使用返回的填充完成的数组 console.log(array.length); console.log(array); // 所有需要使用该数组的逻辑都要放在这个回调内 })
注意:所有需要用到这个异步加载数组内容的逻辑,必须放在异步完成的回调/await之后的作用域内,否则还是会读到空数组。
内容的提问来源于stack exchange,提问作者Dodo1991
相关产品推荐
相关产品推荐

