I'm creating a guest list program that stores the guest list in Firebase RTDB and when I check people in and out my function runs several times more than it is supposed to. I've sent alerts to the console so I know how many times it has run. I have separate functions for both check in and check out operations so it may be that I am calling my db too many times?
//-------------------- Check In and Check In Helper Functions -------------------------
//Helper Function to Grab current List index
function printArray() {
var ref = database.ref('guestList')
ref.on('value', readData, errData);
}
function readData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkIn(guestList);
}
function errData(err){
console.log('Error!');
console.log(err);
}
//Helper Function to set text box to selected name
function checkInn(name){
console.log(name)
document.getElementById('checkIn').value = name;
}
//Check in
function checkIn(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkIn').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "Yes",
TimeIn: getTime(),
})
guestsRef.off();
document.getElementById('checkIn').value = "";
alerts(name, true)
}
})
}
//------------------------- Check Out ------------------------------------------------------------
//Helper Function to Grab current List index
function printArrayy() {
var ref = database.ref('guestList')
ref.on('value', readOutData, errData);
}
function readOutData(data){
guestList=[];
var scores = data.val();
var keys = Object.keys(scores)
for (var i=0; i < keys.length; i++){
var k = keys[i]
var name = scores[k].name;
var inside = scores[k].Inside;
var timeIn = scores[k].TimeIn;
var timeOut = scores[k].TimeOut;
guestList[i] = {
name: name,
Inside: inside,
TimeIn: timeIn,
TimeOut: timeOut,
}
}
checkOut(guestList);
}
//Helper Function to set text box to selected name
function checkOutt(name){
console.log(name);
document.getElementById('checkOut').value = name;
}
//Check Out
function checkOut(list) {
//Grabs current guest to be added or deleted from form text box
var name = document.getElementById('checkOut').value;
//Checks to see if user is in list of guests and isn't in the list of guest in the party
var guestsRef = firebase.database().ref("guestList/");
guestsRef.orderByChild("name").on("child_added", function(data) {
if (name == data.val().name) {
objIndex = list.findIndex((obj => obj.name == name));
guestsRef = firebase.database().ref("guestList/" + objIndex)
guestsRef.update({
Inside: "No",
TimeOut: getTime(),
})
document.getElementById('checkOut').value = "";
guestsRef.off();
alerts(name, false)
}
})
}
//Placeholder to alert user when a succesful check in or check out function runs
function alerts(name, Boolean){
if(Boolean){
console.log(name + " has been checked in!")
}
else{
console.log(name + " has been checked out!")
}
}
Here is the screenshot of my output. Thanks in advance!
Edit: Forgot to mention and apologize for my excessive use of helper functions! My HTML form calls printArrayy() and printArray first for each function!
have you tried once instep on, i mean:
ref.once('value', readOutData, errData); }
I have two buttons: a sign up and a log in. I intend to collect the input form values from the sign up into an array (this works). I then want to compare the user input from the sign up with the user input from the login and notify the user that they are logged in. (I am yet to get started with localStorage and JSON. I want to get this done using arrays first).
I have tried using a for loop and if statements with logical operators (&&).
$(document).ready(function() {
$("#userSignUp").click(function() {
$("#signUpForm").show();
$("#signup").hide();
});
$("#userInfo").click(function(event) {
var custName = $("#newName").val();
var custEmail = $("#newEmail").val();
var custPass = $("#newPass").val();
var custData = [];
custData.push(custName, custEmail, custPass);
$("#userSignUp").text("Thank you for signing up!");
});
$("#userLogIn").click(function() {
$("#loginForm").show();
$("#login").hide();
});
$("#userData").click(function(event) {
var currentName = $("#userName").val();
var currentEmail = $("#userEmail").val();
var currentPass = $("#userPass").val();
for (var i = 0; i < custData.length; i++) {
if ((currentName === custData[0]) && currentEmail === custData[1] && currentPass === custData[2]) {
$("#userLogIn").text("You are logged in!");
} else {
$("#userLogIn").text("Please enter correct name, email and password!");
}
};
});
});
May be you could try only IF statement without the loop.
The following thing checks if there is such item in the array and if it IS, will do smth:
if (custData.indexOf(currentName) != -1
&& custData.indexOf(currentEmail) != -1
&& custData.indexOf(currentPass) != -1) {
$("#userLogIn").text("You are logged in!");
} else {
$("#userLogIn").text("Please enter correct name, email and password!");
I have been learning about localStorage. I decided to use it on this task. I collected the values that the user inputs when signing up, and 'saved' them on local Storage. I then collected the value the user inputs and 'retrieved' them via local Storage. Here is the code:
$(document).ready(function() {
$("#userSignUp").click(function() {
$("#signUpForm").show();
$("#signup").hide();
});
$("#userInfo").click(function(event) {
var custName = $("#newName").val();
var custEmail = $("#newEmail").val();
var custPass = $("#newPass").val();
localStorage.setItem("name", "Raych") +
localStorage.setItem("email", "raych#gmail.com") +
localStorage.setItem("password", "hey"); ;
$("#userSignUp").text("Thank you for signing up!");
});
$("#userLogIn").click(function() {
$("#loginForm").show();
$("#login").hide();
});
$("#userData").click(function(event) {
event.PreventDefault;
var currentName = $("#userName").val();
var currentEmail = $("#userEmail").val();
var currentPass = $("#userPass").val();
localStorage.getItem("name") +
localStorage.getItem("email") +
localStorage.getItem("password");
$("#userLogIn").text("You are logged in!");
});
});
I'm trying to get some for Loops running inside a google cloud functions everytime I delete my /users node.
This is the code I'm using
exports.deleteUserAssets = functions.database.ref('/users/{userId}').onWrite((change, context) => {
const beforeData = change.before.val();
const afterData = change.after.val();
const userBuildings = Object.keys(beforeData.isAdmin); // get the buildings of the user stored in the user/userId/isAdmin node .. so far so good
const userId = beforeData.userIDforCloudFunctions; // I'm getting this from a /users/userid/userIDforCloudFucntions node ...so far so good (i've been logging it to confirm)
// making sure it was a delete operation ... so far so good
if (afterData !== null) {
return 0;
}
else {
// on each building
for (var i = 0; i < userBuildings.length; i++) {
let eachBuilding = [userBuildings[i]]
// HERE IS WERE THE PROBLEM IS: Trying to delete all depts + rooms + doors
admin.database().ref('/buildings/' + eachBuilding)
.child("hasDepts")
.once("value")
.then(function(snapshot) { // This is where it goes south – snapshot is returning null
snapshot.forEach(function(childSnapshot) {
var deptKeyString = childSnapshot.key; // will try to get the keys of the departments stored under this space
var deptsOnNode = admin.database().ref('/depts/' + deptKeyString);
deptsOnNode.remove(); // and use the keys to delete each of the depts on depts
});
});
admin.database().ref('/buildings/' + eachBuilding).set({}); // this is working
admin.database().ref('/buildingsUserUid/' + userId + '/' + eachBuilding).remove(); // this is working
}
}
return 0;
});
The snapshot of admin.database().ref('/buildings/' + eachBuilding).child("hasDepts") is returning null.
How can I get to it? Besides admin.database().ref() I've tried to reach it with firebase.database().ref() which is the command/object i use to get this running on frontend functions. I've also tried functions.database() with no result.
Taking in consideration what Doug Stevenson mentioned in his second comment:
exports.deleteUserAssets = functions.database.ref('/users/{userId}').onDelete((change, context, event) => {
const beforeData = change.before.val(); // data before the write (data of all the doors child nodes)
const afterData = change.after.val(); // data before the write (data of all the doors child nodes)
const userBuildings = Object.keys(beforeData.isAdmin); // get the buildings of the user
const userId = beforeData.userIDforCloudFunctions;
// make sure user was deleted
if (afterData !== null) {
return 0;
}
else {
// on each building
for (var i = 0; i < userBuildings.length; i++) {
let eachBuilding = [userBuildings[i]]
// Need to RETURN the whole chain of promises
return admin.database().ref('/buildings/' + eachBuilding)
.child("hasDepts")
.once("value")
.then(function(snapshot) {
console.log(snapshot.val()) // this now works
snapshot.forEach(function(childSnapshot) {
console.log(childSnapshot.val()) // this works as well
var deptKeyString = childSnapshot.key; // get the keys of the departments stored under this space
var deptsOnNode = admin.database().ref('/depts/' + deptKeyString);
// and you can keep on going deeper if you return promises
return deptsOnNode
.child('hasRooms')
.once('value')
.then(function(grandchildSnapshot){
console.log(grandchildSnapshot.val())
grandchildSnapshot.forEach(function(grandGrandchildSnapshot){
var roomKeyString = grandGrandchildSnapshot.key;
var roomsOnDepts = admin.database().ref('/rooms/' + roomKeyString);
admin.database().ref('/roomOwners/' + userId + '/' + roomKeyString).remove();
// and return again here...
return roomsOnDepts
.child('hasDoors')
.once('value')
.then(function(grandgrandGrandchildSnapshot){
grandgrandGrandchildSnapshot.forEach(function(grandgrandGrandchildSnapshot){
var doorKeyString = grandgrandGrandchildSnapshot.key;
var doorsOnRooms = admin.database().ref('/doors/' + doorKeyString);
doorsOnRooms.remove();
let clipOwners = admin.database().ref('/clipOwners/' + doorKeyString);
clipOwners.remove();
})
roomsOnDepts.remove();
})
})
deptsOnNode.remove(); // use the keys to delete the depts on depts main Node
})
});
admin.database().ref('/buildings/' + eachBuilding).set({});
admin.database().ref('/buildingsUserUid/' + userId + '/' + eachBuilding).remove();
});
}
}
return 0;
});
im pretty new to node.js/mongoose and i run into some difficulties getting my code to work as intended. Basically i have an Array holding some id's in a sorted order and i want to check against my Reservations if they hold those id's on a certain condition (same reservation date, time slot, etc.)
I cant seem to get my logic to work that basically should take following approach: Run through the table array from index 0 to index length-1, for each index there should be a findOne({]) query, if no reservation exists with that table id, a reservation shall be placed and exit the loop, if a reservation exists go to the next index and repeat until the array is iterated through from 0...n (the specific order the array is sorted in is important here, it should always prefer the least matching). If no table id is "free" to make a new reservation it should send a response message that every table is reserved already. Anyone that could help me out on my problem? Would appreciate any hints!
app.post('/api/reservations', (req, res) => {
const resDate = new Date(req.body.reservationDate).toISOString();
const queryDate = new Date(req.body.reservationDate);
const tableDict = req.body.tableDict;
const slot = req.body.timeSlot;
const seats = req.body.seats;
const restaurant = req.body.restaurant;
const customer = req.body.customer;
const comment = req.body.comment;
function gteQueryDate(date) {
return date.toISOString();
}
function lteQueryDate(date) {
date.setDate(date.getDate() + 1);
return date.toISOString();
}
const gteDate = gteQueryDate(queryDate);
const lteDate = lteQueryDate(queryDate);
const sortedTables = [];
for (i = 0; i < tableDict[slot].length - 1; i++) {
if (tableDict[slot][i] !== null && tableDict[slot][i].seats >= seats) {
sortedTables.push([tableDict[slot][i]._id, tableDict[slot][i].seats]);
}
}
sortedTables.sort(function(a, b) {
return a[1] - b[1];
});
var createReservation = function(tableId) {
console.log("called function with id : " + tableId);
Reservation.findOne({
'restaurant': restaurant,
'timeSlot.slot': slot,
'timeSlot.table': tableId,
'reservationDate': {
'$gte': gteDate,
'$lte': lteDate
}
})
.then(reservation => {
if (!reservation) {
console.log("can create reservation with id: " + tableId);
var timeSlot = [{
'slot': slot,
'table': tableId
}];
const newReservation = new Reservation({
seats: seats,
comment: comment,
timeSlot: timeSlot,
customer: customer,
restaurant: restaurant,
reservationDate: resDate
});
newReservation.save()
.then(result => {
res.send(result);
})
.catch(err => {
console.log(err);
});
} else {
console.log("reservation with id: " + tableId + " exists already.");
}
})
.catch(err => {
console.log(err);
});
}
for (j = 0; j < sortedTables.length; j++) {
var tableId = sortedTables[j][0];
createReservation(tableId);
}
});
I am working on small idea to collect errors from pages and to store them in DB and then use graph API to display information visually.
There is 8 sites and on each of them there is 100 entries - so 800 transactions per time.
I loop through each site and then sub-loop through table of errors and collect them.
I got it working if I make insert query on each of those sub-loops for all 800 entries but I am getting some sort of memory leak from so many transactions and after few minutes - Node breaks due to memory exceeding.
So I tried queuing all 800 entries into Array of Arrays and then performing multi-insert at the end of every iteration but I am getting ER_PARSE_ERROR.
var tabletojson = require('tabletojson');
var mysql = require("mysql");
var striptag = require("striptags");
var fs = require("fs");
var path = require('path');
var startCollector;
var iterations = 0;
var insertions = 0;
var duplicated = 0;
var datas = [];
var clients = ["ClientA", "ClientB", "ClientC", "ClientD", "ClientE", "ClientF", "ClientG", "ClientH"];
var appDir = path.dirname(require.main.filename);
var errorList = ["err1", "err2", "err3", "err4", "err5", "err6"];
var con = mysql.createPool({
host: "localhost",
user: "User",
password: "Password",
database: "errors"
});
function CollectErrors() {
startCollector = new Date();
for(var a = 0; a < clients.length; a++) {
(function(a) {
tabletojson.convertUrl("http://example.com" + clients[a] + "/page.php?limit=100", { stripHtmlFromCells: false }, function(response) {
var rs = response[0];
for(var l = rs.length-1; l > -1; l--) {
var newDate = formatDate(striptag(rs[l]["Date"]), striptag(rs[l]["Time"]));
var user = getUser(striptag(rs[l]["User"]));
var msg = striptag(rs[l]["Error"]);
var splitError = rs[l]["Error"].split("<a href=\"");
var link = getUrl(splitError[1]);
var id = getId(link);
var type = getType(striptag(splitError[0]));
var temp = [newDate, link, type, user, clients[a], id, msg];
datas.push(temp);
}
});
})(a);
}
con.getConnection(function(err, connection) {
connection.query("INSERT IGNORE INTO entries (time, url, type, author, client, uid, message) VALUES ?", [datas], function(err, rows) {
console.log(err);
});
connection.release();
datas = [];
});
setTimeout(CollectErrors, 10000);
}
function formatDate(date, time) {
var newdate = date.split("/").reverse().join("-");
var newtime = time+":00";
return newdate + " " + newtime;
}
function getUrl(uri) {
return "http://example.com/"+uri.split("\">Details")[0];
}
function getId(url) {
return decodeURIComponent((new RegExp('[?|&]' + "id" + '=' + '([^&;]+?)(&|#|;|$)').exec(url) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}
function getType(error) {
for(var a = 0; a < errorList.length; a++) {
if(error.indexOf(errorList[a]) !== -1) {
return errorList[a];
}
}
return "Other";
}
function getUser(user) {
if(user == "" || user == " " || user == null) {
return "System";
}
return user;
}
CollectErrors();
I've tried mysql.createConnection too but that also gave me same issue.
I've been stuck for past 12 hours and I can't see what's wrong, I've even tried populating Datas table with just strings but got same error.
I've changed your code to use ES6 and correct modules features.
Useful links: correct pooling with mysql, correct insert query, async/await, IIFE, enhanced object
const tabletojson = require('tabletojson'),
mysql = require("mysql"),
striptag = require("striptags"),
fs = require("fs"),
path = require('path');
const startCollector,
iterations = 0,
insertions = 0,
duplicated = 0;
let datas = [];
const clients = ["ClientA", "ClientB", "ClientC", "ClientD", "ClientE", "ClientF", "ClientG", "ClientH"];
const appDir = path.dirname(require.main.filename);
const errorList = ["err1", "err2", "err3", "err4", "err5", "err6"];
const con = mysql.createPool({
host: "localhost",
user: "User",
password: "Password",
database: "errors"
});
// We'll use async/await from ES6
const collectErrors = async() => {
// Up to here I've only changed syntax to ES6
let startCollector = new Date();
// We'll try to iterate through each client. And we use here for..of syntax to allow us using await
for (let client of clients) {
// Please, check that client value return correct data. If not, change for..of to your for..each and client variable to clients[a]
const tbj = await tabletojson.convertUrl("http://example.com" + client + "/page.php?limit=100", {
stripHtmlFromCells: false
});
const result = tgj[0];
for (rs of result) {
// I can't check this part, but I hope your example was with correct values.
let newDate = formatDate(striptag(rs[l]["Date"]), striptag(rs[l]["Time"]));
let user = getUser(striptag(rs[l]["User"]));
let link = getUrl(splitError[1]);
let msg = striptag(rs[l]["Error"]);
let id = getId(link);
let splitError = rs[l]["Error"].split("<a href=\"");
let getType = getType(striptag(splitError[0]));
// ES6 enhanced object syntax
datas.push({
newDate,
user,
msg,
id,
splitError,
link,
getType,
temp: [newDate, link, type, user, client, id, msg]
});
}
}
// OK, here we have fulfilled datas array. And we want to save it.
con.getConnection((err, connection) => {
// Please, notice, here I've changed your insert query to prepared statement.
connection.query("INSERT IGNORE INTO entries SET ?", datas, (err, rows) => {
console.log(err);
connection.release();
datas = [];
});
});
// I don't see why do you need timeout here, so I've left it commented.
// setTimeout(CollectErrors, 10000);
};
// Here your other methods go....
// And to call your async function we'll use IIFE
(async() => {
await collectErrors();
})();
Probably there may be errors with mysql insert, but that's not for sure. If occurred, please write in comments and I'll help you with that.