Firestore异步函数返回布尔值异常:添加return为何解决问题?
return performanceRef.get()能解决返回异常? 我写了一个用于在Firestore数据库中存储数据的异步函数,需求是先检查目标值是否已存在,再返回对应的布尔值。尝试用async/await实现逻辑但没成功,最后在performanceRef.get()前加了return语句才解决问题。我不清楚这个return的作用原理,想请教:为什么添加这个return就能解决原本的返回异常?
我的代码如下:
export const createUserPerformanceDocument = async (user, currentDate, answer ) => { const createdAt = currentDate.toLocaleDateString('en-US'); const performanceRef = firestore.doc(`performance/${user}`); return performanceRef.get() .then(doc => { if(doc.exists) { const docData = doc.data(); if (docData[createdAt]) { return false } else { try { performanceRef.set({ [createdAt]: { Question: answer } }, { merge: true }) return true } catch(error) { console.log('Error creating performance data!', error.message); return false } } } else { console.log("This user does not exist in the database"); } }) }
核心原因:async函数的返回值规则 + Promise链的传递
咱们一步步拆解这个问题:
1. 没加return时的问题
你写的是async函数,这类函数有个关键特性:如果函数内部没有显式返回一个值,它会自动返回一个已经resolve为undefined的Promise。
当你最初没写return performanceRef.get()的时候,函数执行到performanceRef.get().then(...)这一行,只是发起了一个异步请求,但没有把这个Promise链返回出去。这时候async函数会直接结束,返回一个resolve(undefined)的Promise,而then回调里的逻辑还在后台异步执行。
这就导致调用这个函数的地方,比如用await createUserPerformanceDocument(...)的时候,会提前拿到undefined,而不是你期望的true/false——这就是你遇到的“返回异常”的根源。
2. 加了return之后的变化
当你加上return performanceRef.get(),相当于把整个Promise链(包括后面的.then回调)作为async函数的返回值。这时候:
async函数会识别到你返回的是一个Promise,它会等待这个Promise的状态变化,然后把这个Promise的最终结果作为自己返回的Promise的resolve值。.then回调里你返回的true/false(或者异常分支里的false),会成为这个Promise链最终的resolve值。
简单说,加了return之后,你让async函数把整个异步流程的结果传递了出去,调用者就能正确等待所有逻辑执行完成,拿到预期的布尔值。
补充:用async/await改写会更清晰
既然已经用了async关键字,其实可以把.then换成await,代码可读性会更高,也不容易犯“忘记返回Promise”的错误:
export const createUserPerformanceDocument = async (user, currentDate, answer ) => { const createdAt = currentDate.toLocaleDateString('en-US'); const performanceRef = firestore.doc(`performance/${user}`); try { const doc = await performanceRef.get(); if(doc.exists) { const docData = doc.data(); if (docData[createdAt]) { return false; } else { await performanceRef.set({ [createdAt]: { Question: answer } }, { merge: true }); return true; } } else { console.log("This user does not exist in the database"); return false; // 这里返回明确值,避免调用者拿到undefined } } catch(error) { console.log('Error creating performance data!', error.message); return false; } }
这样整个逻辑是线性的,async/await会自动帮你处理Promise的传递,不用再纠结是否要手动返回Promise链。
内容的提问来源于stack exchange,提问作者sayayin

