问题
Below is a cloud function, that takes data and adds it to two collections in my database. This code returns an "Unhandled Exception" 1 in 10 times. It works most of the time, but randomly returns this error.
Code:
Cloud Function:
let deleteAttributes = (dataArray, attributeArray) => {
for (let i = 0; i < dataArray.length; i++){
currentObject = dataArray[i]
for (let j=0; j < attributeArray.length; j++) {
delete currentObject[attributeArray[j]]
}
}
}
exports.addSafe = functions.https.onCall((data, context) => {
// The HTTP endpoint is going to receive an object with an attribute "data", which is going to contain an array of objects with every single safe data point to add
const attributesToDelete = ["CARTON#", "NO#"] // This first function call is implemented initially because of the first CSV file that I was given, which includes unnecessary columns, like "Carton" or "No". The factory producing the safes should send a CSV file with no unecessary extra data. If they do, this function should theoretically take care of removing those data points, to ensure that the database only holds the necessary data points ;)
deleteAttributes(data, attributesToDelete);
let validated = true;
//validateForm(data);
if (validated === false) {
console.log('Data cannot be validated. Misses the correct attributes')
} else {
for (let i=0; i<data.length; i++) {
db.collection('Safes').add(data[i])
.then((docRef) => {
db.collection('Safes-Hardware').doc(data[i]['Mac address Check']).set({
"ID" : docRef.id
})
.then((value) =>{
console.log("Mac added with ID: ", value.id);
return { message: "Success is within the palm of our hands." }
})
.catch(err => {
console.log('Oops!, error while adding lookup details',err);
return { message: "Error while adding lookup details",err }
})
console.log('Mac written with ID: ', data[i]['Mac address Check']);
return { message: "Success is within the palm of our hands." }
})
.catch(err => {
console.log('Error logged', err);
})
}
}
})
Updated Cloud Function - (Using async-await)
let deleteAttributes = (dataArray, attributeArray) => {
for (let i = 0; i < dataArray.length; i++){
currentObject = dataArray[i]
for (let j=0; j < attributeArray.length; j++) {
delete currentObject[attributeArray[j]]
}
}
}
exports.addSafe = functions.https.onCall((data, context) => {
// The HTTP endpoint is going to receive an object with an attribute "data", which is going to contain an array of objects with every single safe data point to add
const attributesToDelete = ["CARTON#", "NO#"] // This first function call is implemented initially because of the first CSV file that I was given, which includes unnecessary columns, like "Carton" or "No". The factory producing the safes should send a CSV file with no unecessary extra data. If they do, this function should theoretically take care of removing those data points, to ensure that the database only holds the necessary data points ;)
deleteAttributes(data, attributesToDelete);
let validated = true;
//validateForm(data);
if (validated === false) {
console.log('Data cannot be validated. Misses the correct attributes')
} else {
for (let i=0; i<data.length; i++) {
try
{
// eslint-disable-next-line no-await-in-loop
var ifPresent = db.collection("Safes-Hardware").doc(data[i]['Mac address Check']);
ifPresent.get()
.then(async (doc)=>{
if (!doc.exists)
{
console.log("Document does not exit. Proceeding to add");
try{
// eslint-disable-next-line no-await-in-loop
const docRef = await db.collection('Safes').add(data[i])
console.log('Mac written with ID: ', docRef.id);
try{
// eslint-disable-next-line no-await-in-loop
await db.collection('Safes-Hardware').doc(data[i]['Mac address Check'])
.set({
"ID" : docRef.id
})
console.log("Reference added");
}
catch(err){
console.log("Error while adding reference",err)
}
}
catch(err){
console.log("Error while adding data to 'Safe' collection")
}
}
else
{
console.log("Document exists in database. Skipping safe with MAC Address: ",data[i]['Mac address Check']);
}
return { message: "Success is within the palm of our hands." }
})
.catch((error)=>{
console.log("Error while checking for duplicates", error);
});
}
catch(error){
console.log("Error logged",error)
}
}
}
})
Invoked here:
handleUpload = async (event) => {
event.preventDefault();
let data = this.state.file.data;
// let uploadedFile = this.state.file;
console.log('Data variable before file upload', data);
if (data.length > 0) {
const firstSafeObject = data[0];
const fileValidated = True ;// Validates that the file uploaded contains safe-related properties
if (fileValidated === true) { // IMPORTANT-TOMODIFY: If you want to simply validate all files, you can change the statement inside to (true)
let dataObj = { // so that it theoretically goes through every time. There's another layer of validation on the backend so even then, a random
"data": data // file that does not contain the necessary attributes will not go through. Go ahead and try :)
}
try {
const addedDataResults = await axios.post(
'https://us-central1-silo-c8eef.cloudfunctions.net/addSafe', // TOCHANGE: You should probably make this an environment variable
dataObj
)
console.log('Data added to DB successfully');
console.log('Data', addedDataResults)
// Changes the state to activate success message for user
//Storing the uploaded file on firebase storage
let bucketName = "Files"
let fileToUpload = this.state.originalFile
let storageRef = firebase.storage().ref(`${bucketName}/${fileToUpload.name}`)
let uploadTask = storageRef.put(fileToUpload)
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
()=>{
let downloadURL = uploadTask.snapshot.downloadURL
console.log('File uploaded to added to Storage successfully at location: ',downloadURL);
console.log('File', fileToUpload)
})
this.setState({
successfullyUploaded: true,
inputKey: Date.now(),
})
// Clears out the input to prevent the file from being mistakenly uploaded twice
} catch(error) {
console.log('Data not added to Firebase DB successfully')
alert('Data not added to DB. Make sure the CSV file is correct.')
}
} else {
alert('File is not a safe file or data format incorrect. Please upload safe file with the correct properties.');
}
}
}
Error: This is the error logged in my cloud function log
The below error is seen in my cloud functions log (addSafe) In the handle upload function - everything works out and the final console.log is "Data added to DB successfully"
Unhandled rejection
addSafe
FetchError: request to https://www.googleapis.com/oauth2/v4/token failed, reason: socket hang up
at ClientRequest.<anonymous> (/srv/node_modules/node-fetch/lib/index.js:1455:11)
at emitOne (events.js:116:13)
at ClientRequest.emit (events.js:211:7)
at TLSSocket.socketErrorListener (_http_client.js:401:9)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at emitErrorNT (internal/streams/destroy.js:66:8)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
In the link below,
https://html.developreference.com/article/12811746/Unhandled+Rejection+in+Google+Cloud+Functions
I read that this happens when I am missing catch() in the code. What am I missing?
Important Note
The code works fine most of the time. I get the correct output. But sometimes I get the above mentioned error saying socket hang up. Does this have something to do with the server? Or if not, what error am i not handling?
来源:https://stackoverflow.com/questions/62314213/handling-unhandled-exception-in-react-firebase-project