问题描述
const admin = require('firebase-admin')
admin.initializeApp()
exports.setSessionState = functions.https.onCall(async (data,context) => {
const stateId = data.stateId
const details = data.details
const stateRef = admin.database().ref(`state/${stateId}`)
stateRef.transaction((state) => {
if (state) {
state.details = details
}
return state
})
})
该代码在实际的应用程序中运行良好,并且状态已更新,但是在状态始终为null
的测试中运行时,我遇到了问题。 (换句话说,永远不会设置细节。)该测试使用Mocha框架,并且在一个真实的Firebase项目上运行,我看不到这里会有什么不同,但是当从客户端应用程序以及从测试套件中调用它时:
const chai = require('chai')
const assert = chai.assert
const test = require('firebase-functions-test')({
databaseURL: '<redacted>',storageBucket: '<redacted>',projectId: '<redacted>',},'../service-account-credentials.json')
describe('CFsetSessionState',() => {
let wrapped
let cloudFunctions
let admin
before(() => {
cloudFunctions = require('../index')
admin = require('firebase-admin')
wrapped = test.wrap(cloudFunctions.CFsetSessionState)
})
it('Test setting state',async () => {
const stateId = 'abc'
const data = {
stateId: stateId,details: {
name: 'New name'
}
}
const context = {
auth: {
uid: 123
}
}
const stateRef = admin.database().ref(`state/${stateId}`)
await stateRef.set({
name: 'PrevIoUs name',active: true
})
await wrapped(data,context)
const snapshot = await stateRef.once('value')
const state = snapshot.val()
// Details do not exist here,why?
assert.equal(state.details.name,'New name')
})
})
在测试之后,我将数据库状态保持不变,因此我可以看到状态对象中确实存在数据,但是未设置详细信息。在调用云函数之前和之后进行一些设置和获取数据的实验(使用.once()
可以改变行为,使我认为这可能是一些缓存问题,但是这种实验并没有给我任何特别的稳定性结束状态。我不知道等效的本地缓存在云功能中如何工作,它目前显示随机行为。
是什么原因造成的?
解决方法
我还没有尝试过通过测试运行您的Cloud Function,但是很可能是由于您错误地管理Cloud Function的生命周期这一事实造成的。由于它是可调用的,因此您需要通过返回Promise(或所有异步工作完成时的值)来终止它。文档中的更多详细信息here和here。
因此,您应该按照以下方式调整CF:
exports.setSessionState = functions.https.onCall(async (data,context) => {
const stateId = data.stateId
const details = data.details
const stateRef = admin.database().ref(`state/${stateId}`)
return stateRef.transaction((state) => { // Note the return here
if (state) {
state.details = details
}
return state
})
})
我们将返回Promise返回的Transaction。