Let's begin by correcting the indentation in your code.
exports.functionTST = functions.https.onCall(async (data, context) => {
const promises = [];
JSON.parse(JSON.stringify(data), (key, value) => {
// parse values
});
// set values
promises.push(
admin.database()
.ref('game/' + matchkey + '/'...)
.update({
val1: val2,
})
);
// counter
admin.database()
.ref('game/' + matchkey)
.once('value')
.then(datasnapshot => {
let counter = datasnapshot.child("counter").val();
if (counter === null) {
promises.push(admin.database().ref('game/' + matchkey + '/counter').set(1));
} else if (counter < 3) {
promises.push(admin.database().ref('game/' + matchkey + '/counter').set((counter + 1)));
} else if (counter == 3) {
promises.push(admin.database().ref('game/' + matchkey + '/counter').remove());
// do other stuff
}
});
Promise.all(promises);
return null;
});
Your code has a few issues that need to be addressed.
The main problem is that you are not properly handling the asynchronous nature of your Promises. Failing to await or return the Promise chain correctly can lead to throttling and potential skipping of network requests like database updates.
await Promises.all(promises); // <- added await here
return null; // indicating no data to return
You should modify this section to either:
await Promises.all(promises);
return null; // indicating no data to return
or
return Promises.all(promises)
.then(() => null); // indicating no data to return
The following block of code seems redundant as it doesn't store the result of JSON.parse
. Consider using Object.entries(data)
based on your requirement.
JSON.parse(JSON.stringify(data), (key, value) => {
// parse values
});
This part creates a stray Promise without proper handling, leading to inconsistent behavior. It needs to be stored in the promises
array for consistency.
admin.database()
.ref('game/' + matchkey)
.once('value')
.then(/* ... */);
You should replace the above block with a transaction operation to streamline database updates and ensure accuracy.
// set values
promises.push(
admin.database()
.ref('game/' + matchkey + '/'...)
.update({
val1: val2,
})
);
// counter
admin.database()
.ref('game/' + matchkey)
.once('value')
.then(datasnapshot => {
let counter = datasnapshot.child("counter").val();
if (counter === null) {
promises.push(admin.database().ref('game/' + matchkey + '/counter').set(1));
} else if (counter < 3) {
promises.push(admin.database().ref('game/' + matchkey + '/counter').set((counter + 1));
} else if (counter == 3) {
promises.push(admin.database().ref('game/' + matchkey + '/counter').remove());
//do other stuff
}
});
Promises.all(promises);
return null;
By implementing the above changes and merging your logic, the function can be simplified like so:
//counter
await admin.database()
.ref('game/' + matchkey)
.transaction((matchInfo) => {
if (matchInfo) {
matchInfo[/* The '...' from .ref('game/' + matchkey + '/'...) */].val1 = val2;
const counter = matchInfo.counter || 0;
if (counter < 3) {
matchInfo.counter = counter + 1;
} else {
delete matchInfo.counter;
// handle additional tasks like declaring a winner
}
}
return matchInfo;
});
return null;
The final version of your function could resemble the following structure:
exports.functionTST = functions.https.onCall(async (data, context) => {
try {
const matchkey = data.matchkey;
/* ... */
} catch (err) {
console.log('Unexpected error while handling request data: ', err);
throw new functions.https.HttpsError('invalid-argument', 'Could not parse request data');
}
try {
await admin.database()
.ref('game/' + matchkey)
.transaction((matchInfo) => {
/* ... */
});
} catch (err) {
console.log('Unexpected error while updating match information: ', err);
throw new functions.https.HttpsError('internal', 'Could not update match information');
}
return null;
}