setTimeout() in Node.js - node.js

I am writing cloud functions on Cloud Firestore triggers. What I want is when a document is added under some uuid it has to deleted after 2 minutes and assign the same data to another document. I wrote some code regarding that like below
exports.createdOpenOrder = functions.firestore.document('Some/{psId}/Open/{OrderId}').onCreate((snap, context) => {
// Get an object representing the document
console.log("Deleting function execution started:");
const newValue = snap.data();
var OrderId = context.params.OrderId;
var psId = context.params.psId;
setTimeout(delete_cur, 120000);
function delete_cur() {
var data = db.collection('Some').doc(psId).collection('Open').doc(OrderId).delete().then(function() {
console.log("Document successfully deleted!");
// calling another function to reassign
reassign(OrderId);
return;
}).catch(function(error) {
console.error("Error removing document: ", error);
return;
});
}
});
Now my problem is the setTimeout function is not calling exactly after 2 minutes and data is not deleting. Is anything wrong with my code? Please let me know how to write code work perfectly on setTimeout.

To find the problem, put log before, and a catch around, the contents of your setTimeout handler.
Currently you are only trapping exceptions after the delete async function returns. All other exceptions in the chain, before calling delete, are not caught.
function delete_cur() {
console.log('handler called')
try {
var data = db.collection('Some').doc(psId).collection('Open').doc(OrderId).delete().then(function() {
console.log("Document successfully deleted!");
// calling another function to reassign
reassign(OrderId);
return;
}).catch(function(error) {
console.error("Error removing document: ", error);
return;
});
} catch (e) {
console.error('could not invoke delete', e)
}
}

Related

How to execute Request one after other

Library - Tedious
var productsIds = []
const getProductsIdsRequest = new Request(GET_PRODUCT_ID_QUERY, function (err) {
if (err) {
console.log(err);
} else {
connection.close()
}
});
getProductsIdsRequest.on("row", function (columns) {
//collecting products Ids
})
getProductsIdsRequest.on("requestCompleted", async function (rowCount, more) {
//Performing some operations on the data
updateColumnInTable()
})
const updateColumnInTableRequest = new Request(UPLOAD_PRODUCT_ID_QUERY, function (err) {
if (err) {
console.log(err);
} else {
connection.close()
}
});
I need to run two requests, first GET_PRODUCT_ID_QUERY and second UPLOAD_PRODUCT_ID_QUERY. After fetching the product id's and doing some operations on the them, I need to run the 2nd query to update it. How I can do this? I have tried to run the update function inside the "requestCompleted" event, but it's throwing me error that I can't run another request in the final state. Note inside "requestCompleted" event, I am doing some heavy operations on Id's and after that only I need to call the update function(2nd request)

Handling Multiple functionalities in Firebase using Nodejs

Hellow all,
I'm Newbie to Nodejs and Firebase, I need two functionalities to takes place in a single function and also I have written a piece of code it's works fine.
But My question is, the code I have written is the correct way to achieve the multiple functionality or do we have any other alternate method(correct way) to achieve the same functionality.
Doubt :
Retrieving relevant details of project ----> Inside Callback function ----> saving data to another table ----> Inside Callback function ----> Deleting data from table -----> Inside Callback function ----> response
Do we need to write the functionality inside the nested callback function to achieve the output or is there is any other way to achieve it .
// Nodejs Post Function
app.post('/delete_user_request_project/', function (req, res)
{
if (!is_admin_login(req.cookies.login_type))
{
return res.redirect('/');
}
var project_id = req.body.project_id; // Getting the project Id
let del_ref = admin.database().ref("user_request_project/" + project_id); // Targeting the details of the project to fetch that particular data
del_ref.once("value", function (snapshot)
{
var request_project_obj = snapshot.val(); // fetching the details of project
if (request_project_obj != null)
{
let update_ref = admin.database().ref("deleted_user_request_project/" + project_id);
update_ref.set(
request_project_obj // Updating project details to another table
).then(function ()
{
del_ref.remove().then(function () // Deleting the details from project Table
{
return res.status(200).send('success');
});
});
}
else
{
var error = "プロジェクトが存在しない";
req.flash("error", error_message);
return res.send({
status: 'error',
error: error
});
}
});
})
TIA
I would suggest you use the Promise version of the once() method instead of the Callback version, as follows. It will allow you to correctly chain the different promises returned by the asynchronous Firebase method.
app.post('/delete_user_request_project/', function (req, res) {
if (!is_admin_login(req.cookies.login_type)) {
return res.redirect('/');
}
var project_id = req.body.project_id; // Getting the project Id
let del_ref = admin.database().ref("user_request_project/" + project_id); // Targeting the details of the project to fetch that particular data
del_ref.once("value")
.then(function (snapshot) {
var request_project_obj = snapshot.val(); // fetching the details of project
if (request_project_obj != null) {
let update_ref = admin.database().ref("deleted_user_request_project/" + project_id);
return update_ref.set(request_project_obj); // Updating project details to another table
}
else {
throw new Error('request_project_obj null');
}
})
.then(function () {
return del_ref.remove();
})
.then(function () // Deleting the details from project Table
{
return res.status(200).send('success');
})
.catch(function (error) {
if (error.message === 'request_project_obj null') {
var error = "プロジェクトが存在しない";
req.flash("error", error_message);
return res.send({
status: 'error',
error: error
});
} else {
//...
}
})
})

NodeJs/React- How to store query results from firestore in variable

function collectres () {
var store ='';
var docRef = db.collection("cities").doc("SF");
docRef.get()
.then(function (doc) {
if (doc.exists) {
console.log("Document data:", doc.data());
store = doc.data();// when referenced outside, it doesnt hold anything.
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function (error) {
console.log("Error getting document:", error);
});
return store; // returns nothing and seems to not notice the assignment.
}
I have this problem, where i want to store firebase query results into a variable. However, when i try and assign the variable some data from the query, it seems to not be able to store it.
Any help or advice in the right direction would help.
Edit 1:
After implementing the callback function, i was wondering how to set the state for a component or permanently store the results so that many components can access it.
user.CollectRes(function(store){
console.log(store.name);
name =store.name;
console.log(name);
// this.setState({name:store.name});
});
console.log(name); // want to be able to reference this outside the callback function. So i can display it on the page.
It is because JavaScript is asynchrone.
Because of that, your variable doc doesn't exists yet outside your .then function.
To return this value, you can use Promises way, or easier, you can have a callback function to return your document like this :
function collectres (callback) {
var docRef = db.collection("cities").doc("SF");
docRef.get().then(function (doc) {
if (doc && doc.exists) {
callback(doc.data()); // Return your data inside the callback function
} else {
callback(null); // Return null if data doesn't exists
}
}).catch(function (error) {
callback(null); // Return null in error case
});
}
collectres(function (store) { // Call collectres to get your data
console.log(store);
// continue here
});
I recommand you to read this article to learn more about asynchronous.
Hope it helps.

NodeJS - How does connection.rollback() work with async.parallel

I'm totally new to nodejs. I would like to ask your expertise regarding for error handling using connection.beginTransaction(); with this sample code.
connection.beginTransaction(function(){
async.parallel([
function(callback){
connection.query('INSERT INTO SUBJECT.PROJECT (Name, Score) VALUES (?,?)',
['Drake', '85']
, function(error){
//if(error)
// connection.rollback();
callback(error);
});
},
function(callback){
connection.query(someUpdateQuery, someValues,
function(error){
//if(error)
// connection.rollback();
callback(error);
});
}
], function(error){
var msg;
if(error) {
connection.rollback();
msg = 'Error! ' + error;
}
else {
connection.commit();
msg = 'Success';
}
res.json(msg);
});
});
With this sample code, Is this doable?
Every connection.query has connection.rollback() in if(error), can I remove connection.rollback() in each
connection.query and rely in the last function instead to handle the
connection.rollback()? - will it rollback all (lets say) 10 inserting query functions then the 5th 1 got the error.
Sorry, I don't know much,. thanks for reading
You are correct - you can remove the rollback statements of the individual queries and rely on the one in the async.parallel callback. Your code would look something like this:
connection.beginTransaction(function () {
async.parallel([
function (callback) {
connection.query('INSERT INTO SUBJECT.PROJECT (Name, Score) VALUES (?,?)',
['Drake', '85']
, callback);
},
function (callback) {
connection.query(someUpdateQuery, someValues, callback);
}
], function (error) {
var msg;
if (error) {
connection.rollback();
msg = 'Error! ' + error;
}
else {
connection.commit();
msg = 'Success';
}
res.json(msg);
});
});
This works because non of the commands will be committed to the database until you call connection.commit() in the final callback. One thing you might want to look at is whether the commit and rollback methods are asynchronous, i.e. they expect you to pass a callback to them. If so your code as it is will run res.json before the transaction has been committed or rolled back.

How do I return error header if a db call throws an error?

I have a small data gathering web app running with NodeJS and Couchbase. The requirement is, that when a 3rd party pushes some data to us and we are able to process it, we return the 200 header, but if there are any problems with storing that data, we return 500. This means that they can re-try with the failed data batch.
I'm having an issue where the 200 is always returned (because the DB calls are completed asynchronously). Here's an example:
...
var app = express();
function create(req, res) {
var error = false;
// Parse all the entries in request
for (var i = 0; i < req.body.length; i++) {
var event = req.body[i];
if (!event.email) {
// log error to file
error = true;
res.send("Event object does not have an email address!", 500);
}
// Greate the id index value
var event_id = 'blah';
// See if record already exists
db.get(event_id, function (err, result) {
var doc = result.value;
if (doc === undefined) {
// Add a new record
db.add(event_id, event, function (err, result) {
if (err) {
error = true;
res.send('There were processing errors', 500);
}
});
}
});
}
if (error)
res.send("Try again", 500);
else
res.send("OK", 200);
}
app.post('/create', create);
Is there a way of making the app wait for those DB calls to complete, i.e. for this funciton to be synchronous? Or am I using a wrong tech for this? :(
I decided to go with NodeJS+Couchbase because we are likely to have a very high amount of calls, where the data (small JSON objects) must be written, read and deleted. EDIT: Ah the data structure is likely to change for various events, so being able to store non-uniformly shaped documents its of a great advantage!
This is a typical use case for the async library, which is a utility-belt library with lots of patterns to work with asynchronous functions.
Since you need to call an asynchronous function for each record, you can use async.each, which executes an asynchronous function for all elements of an array. A last callback is called when all asynchronous tasks are finished.
var app = express();
function handleEvent = function (event, callback) {
if (! event.email) {
callback(new Error('Event object does not have an email address!'));
}
var event_id = 'blah';
db.get(event_id, function (err, result) {
var doc = result.value;
if (doc === undefined) {
// Add a new record
db.add(event_id, event, function (err, result) {
if (err) {
callback(new Error('There were processing errors'));
}
else {
callback(null);
}
});
}
});
}
function create(req, res) {
// https://github.com/caolan/async#each
async.each(req.body, handleEvent, function (err) {
if (err)
res.send(err.message, 500);
else
res.send('OK', 200);
});
}

Resources