Javascript execution order when pulling Firebase data - javascript

After I authenticate to Firebase with Google auth, I get this console.log output and the JavaScript seems to bounce around in execution order. Here's my console output and the javascript code.
Why does "controller is: Pellet_Pirate_1" display at the log end rather than at the beginning where the code executes to pull this value from Firebase? My "GLOBAL CONTROLLER" and other logs of the contr global variable should be valued as well... I am trying to use contr as a global variable and it is defined at the top of my script tag
Any help would be greatly appreciated... I've banged my head on this one for many hours now!
console.log
<script type="text/javascript">
var contr = undefined;
function PelletPirate() {
this.userPic = document.getElementById('user-pic');
this.userName = document.getElementById('user-name');
this.signInButton = document.getElementById('sign-in');
this.signOutButton = document.getElementById('sign-out');
this.signOutButton.addEventListener('click', this.toggleSignOut.bind(this));
this.signInButton.addEventListener('click', this.toggleSignIn.bind(this));
this.initFirebase();
}
// Sets up shortcuts to Firebase features and initiate firebase auth.
PelletPirate.prototype.initFirebase = function() {
//FlymanEdit Shortcuts to Firebase SDK features.
this.auth = firebase.auth();
this.database = firebase.database();
this.storage = firebase.storage();
//FlymanEdit Initiates Firebase auth and listen to auth state changes.
this.auth.onAuthStateChanged(this.onAuthStateChanged.bind(this));
};
PelletPirate.prototype.toggleSignIn = function() {
var provider = new firebase.auth.GoogleAuthProvider(); // [Start createprovider]
provider.addScope('https://www.googleapis.com/auth/plus.login'); // [START addscopes]
this.auth.signInWithPopup(provider).then(function(result)
{
var token = result.credential.accessToken;
var user = result.user;
console.log('token: ' + token);
}).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential; // The firebase.auth.AuthCredential type that was used.
if (errorCode === 'auth/account-exists-with-different-credential') {
alert('You have already signed up with a different auth provider for that email.');
}
else {
console.error(error);
}
});
}
// Sign-out.
PelletPirate.prototype.toggleSignOut = function() {
this.auth.signOut();
console.log('******************** USER SIGNED OUT *********************');
};
PelletPirate.prototype.onAuthStateChanged = function(user) { // Triggers when user's auth state changes.
if (user) { // User is signed in!
// let's go fetch the Pellet Pirate controller name based on the logged in user!
console.log('user.uid is: ' + user.uid);
firebase.database().ref().child("owners").orderByChild("userId").equalTo(user.uid).on('value', function (snapshot) {
snapshot.forEach(function(childSnapshot) {
contr = childSnapshot.val().controller;
//MYLIBRARY.init([controller, 1, "controller"]);
//MYLIBRARY.passVar();
console.log('controller is: ' + contr);
return contr;
});
});
var currentDate = new Date();
var profilePicUrl = user.photoURL;
var userName = user.displayName;
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var refreshToken = user.refreshToken;
var providerData = user.providerData;
//console.log('You have signed in: ' + userName );
console.log('*************** signed in: ' + userName + ' *****************');
console.log('GLOBAL CONTROLLER: ' + contr);
document.getElementById('authed').style.visibility = 'visible';
document.getElementById('authed2').style.visibility = 'visible';
document.getElementById('gauges').style.visibility = 'visible';
document.getElementById('graph').style.visibility = 'visible';
document.getElementById('parameters').style.visibility = 'visible';
document.getElementById('ParmForm').style.visibility = 'visible';
document.getElementById('ClearDataButton').style.visibility = 'visible';
document.getElementById('AddProgramButton').style.visibility = 'visible';
document.getElementById('programrows').style.visibility = 'visible';
// Set the user's profile pic and name.
this.userPic.style.backgroundImage = 'url(' + profilePicUrl + ')';
this.userName.textContent = userName;
// Show user's profile and sign-out button.
this.userName.removeAttribute('hidden');
this.userPic.removeAttribute('hidden');
this.signOutButton.removeAttribute('hidden');
// Hide sign-in button.
this.signInButton.setAttribute('hidden', 'true');
console.log('before firebase controller is: ' + contr);
//controllerName = "Pellet_Pirate_1";
//Firebase
var TempsRef = Ref.child('ControllerData/' + contr + '/Temps');
console.log('after firebase controller is: ' + contr);
TempsRef.limitToLast(3600/3*16).once("value", function(snapshot) { //Limit to last 16 hours
var Ts = snapshot.val();
for (var k in Ts) {
T1.push([Ts[k].time, Ts[k].T1]);
T2.push([Ts[k].time, Ts[k].T2]);
T3.push([Ts[k].time, Ts[k].T3]);
TT.push([Ts[k].time, Ts[k].TT]);
console.log('in snapshot');
}
TempsRef.limitToLast(1).on("child_added", function(snapshot, prevChildKey) { //Establish callback
var Ts = snapshot.val();
T1.push([Ts.time, Ts.T1]);
T2.push([Ts.time, Ts.T2]);
T3.push([Ts.time, Ts.T3]);
TT.push([Ts.time, Ts.TT]);
UpdatePlot();
console.log('in snapshot-previousChildKey' );
//console.log('in snapshot-PCK-controllerName is:' + controllerName);
});
UpdatePlot();
});
TempsRef.on("child_removed", function(snapshot, prevChildKey) {
T1 = [];
T2 = [];
T3 = [];
TT = [] ;
UpdatePlot();
});
}
else { // User is signed out!
// Hide user's profile and sign-out button.
this.userName.setAttribute('hidden', 'true');
this.userPic.setAttribute('hidden', 'true');
this.signOutButton.setAttribute('hidden', 'true');
document.getElementById('authed').style.visibility = 'hidden';
document.getElementById('authed2').style.visibility = 'hidden';
document.getElementById('gauges').style.visibility = 'hidden';
document.getElementById('graph').style.visibility = 'hidden';
document.getElementById('parameters').style.visibility = 'hidden';
document.getElementById('ParmForm').style.visibility = 'hidden';
document.getElementById('ClearDataButton').style.visibility = 'hidden';
document.getElementById('AddProgramButton').style.visibility = 'hidden';
document.getElementById('programrows').style.visibility = 'hidden';
// Show sign-in button.
this.signInButton.removeAttribute('hidden');
// undefine the controller
contr = undefined;
}
}; // [ END onAuthStateChanged - auth state listener]

Because on() is asynchronous. It returns immediately while the query is happening in the background. Meanwhile, the code immediately after that runs until the first time the callback you provided to it is invokes with a snapshot of results.

Related

Socket.io / Node.js Message send to bad users

i am trying to do an message system (only conversation one user to one user) with mongoDB, node.js and socket.io all is working fine but when i send a message all the users receive it ... I will try to explain you better :
When 4 users are connected (2 in one chat and 2 other in an other chat)
User 1 : Chat a
User 2 : Chat a
User 3 : Chat b
User 4 : Chat b
When user 1 send a message : User 1, 2, 3, 4 see the message but only user 1 and 2 have the message save in database (so when i refresh all user : only user 1 and 2 have the message)
And here is the problem my messages are well saved but when someone send a message the socket send the message to all the users connected
Here is my code : server.js
var http = require('http');
var MongoClient = require('mongodb').MongoClient;
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'Database';
MongoClient.connect(url, function(err, client) {
if (err)
throw err;
console.log('MongoDB connected ...');
httpServer = http.createServer(function(req, res) {
console.log('This is a test');
res.end('Hello World');
});
httpServer.listen(1337);
var io = require('socket.io').listen(httpServer);
var users = {};
var messages = [];
io.sockets.on('connection', function (socket) {
const collection = client.db(dbName).collection('MessageUser');
var me = false;
var friend = false;
var conv = false;
for(var k in users) {
socket.emit('new_user', users[k]);
}
/**
* Login
*/
socket.on('login_chat', function (user) {
me = user;
friend = user.friend;
conv = user.conv;
console.log('New user : ', me.username, ' - id : ', me.id);
users[me.id] = me;
io.sockets.emit('new_user', me);
});
/**
* Disconnect
*/
socket.on('disconnect', function() {
if (!me) {
return false;
}
delete users[me.id];
io.sockets.emit('disc_user', me);
});
/**
* Message receive
*/
socket.on('new_msg', function(message){
if (message.message !== '') {
message.user = me;
date = new Date();
message.h = date.getHours();
message.m = date.getMinutes();
message.y = date.getFullYear();
message.m = date.getMonth();
message.d = date.getDate();
console.log(message);
messages.push(message);
msg = {};
msg.content = message.message;
msg.sendAt = new Date();
msg.idTransmitter = me.id;
msg.idReceiver = friend;
msg.idConversation = conv;
collection.insertOne(msg);
console.log(msg.idReceiver, msg.idTransmitter, me);
io.sockets.emit('new_msg', message, me, msg.idReceiver, msg.idTransmitter);
}
});
});
});
And client.js :
(function($){
var socket = io.connect('http://localhost:1337');
var lastmsg = false;
startTchat = function(user_id, username, friend_id, conv_id) {
socket.emit('login_chat', {
id : user_id,
username : username,
friend : friend_id,
conv : conv_id,
})
};
/**
* Error
*/
socket.on('error', function(err){
alert(err);
});
/**
* Messages
*/
$('#chat_form').submit(function(event){
event.preventDefault();
socket.emit('new_msg', {message: $('#message').val() });
$('#message').val('');
$('#message').focus();
});
socket.on('new_msg', function(message, me, id_receiver, id_transmiter){
if (me.id === id_receiver || me.id === id_transmiter) {
if (lastmsg != message.user.id) {
*(here i add a div with the msg)*
lastmsg = message.user.id;
} else {
*(here too)*
}
}
});
/**
* Login
*/
socket.on('new_user', function(user){
*(here i add a div with new user)*
});
/**
* Disconnect
*/
socket.on('disc_user', function(user){
$('#' + user.id).remove();
})
})(jQuery);
My idea was this line : if (me.id === id_receiver || me.id === id_transmiter) (client.js line 33) but that seems doing nothing ...
So should i add something or maybe my condition is not good ...
ps : That's one of my first time using node, js and socket so i hope i explain well and ask me if you need more info or screenshots maybe :)

When pushing user to array, multiple Array's being created

I'm creating an application (chat app) and I'm pushing each username to an array. Using socket.io, whenever I call an event to push the username to the client side array, multiple instances of the array are created.
For example, the first user I log is fine, Then when another user is added, the array will double, then triple and so on. Thank you in advance for the help . The emit event in which I'm doing this is in the USERS_CONNECTED event.
I am also sorry for the terrible sloppiness of the code below.
Server
const express = require('express');
const fs = require('fs');
const path = require('path');
const http = require('http');
const socketIO = require('socket.io');
const publicPath = path.join(__dirname, 'public');
const port = process.env.PORT || 3001;
let app = express();
let server = http.createServer(app);
var io = socketIO(server);
let username;
app.use(express.static(publicPath));
let usersOnline = []; //keeps track of current users online
io.on('connection', (socket) => {
let user = socket.id;
socket.emit('user', user);
socket.id = "anon";
socket.on('new user', function(data,callback) {
//if user name is taken
if(usersOnline.indexOf(data) != -1 || data == ''){
callback(false);
}else{
//if username is not taken
callback(true);
socket.id = data;
username = data;
//pushes data(username) to data
usersOnline.push(socket.id);
//sends back to client usersOnline array
io.sockets.emit('USERS_CONNECTED', {usersOnline: usersOnline, user: socket.id});
console.log(usersOnline.length)
}
});
socket.on('disconnect', () => {
usersOnline.splice(usersOnline.indexOf(socket.id), 1);
//emits count users, sets current user
io.sockets.emit('USERS_CONNECTED', {usersOnline: usersOnline, user: socket.id});
console.log(usersOnline.length)
});
socket.on('send msg' , function(data){
io.sockets.emit('send msg', {msg: data, user: socket.id});
})
});
server.listen(port, () => {
console.log('server is running master')
});
Client
let socket = io();
let input = document.querySelector('#input_username');
let form = document.querySelector('form')
let userName_page = document.querySelector(".userName_page");
let chat_page = document.querySelector(".chat_page");
let chatWrapper = document.querySelector(".chat_wrapper")
let counter = document.getElementById("counter");
let users = document.querySelector(".users_online")
let join_btn = document.querySelector(".button-effect")
let msg_input = document.querySelector("#sendMsg");
let btn_send = document.querySelector("#send_btn");
let onlineUsers = [];
let sent_ = document.querySelector(".sent_");
let receive_ = document.querySelector(".receive_");
let newUser_text = document.querySelector(".welcome_box")
let user;
let isTyping = document.querySelector('#isTyping')
let welcome_header = document.querySelector("#welcome_header");
let users_online_container = document.querySelector(".users_online");
join_btn.addEventListener("click", function(e){
e.preventDefault();
user = input.value;
//sets user name to input.value
socket.emit('new user', input.value, function(data){
if(data){
userName_page.style.display = "none"
chat_page.style.display = "flex";
welcome_header.innerHTML = input.value + ' has joined the party';
addAnimation();
}else{
if(input.value == ''){
input.classList.add("input_error");
let error_msg = document.getElementById('error_input');
error_msg.innerHTML = '*Invalid, Please Type a Username'
error_msg.style.display = "block";
input.style.border = "2px solid #d9534f";
}else{
input.classList.add("input_error");
let error_msg = document.getElementById('error_input');
error_msg.style.display = "block";
error_msg.style.border = "2px solid #d9534f"
error_msg.innerHTML = "Woops, sorry but that user name is already taken, please try again";
}
}
});
//sets up new user
socket.on('USERS_CONNECTED' , function (data){
//counts online users currently
counter.innerHTML = (data.usersOnline.length + " Online");
for(let i = 0; i < data.usersOnline.length; i++){
onlineUsers.push(data.usersOnline);
let h = document.createElement("h3");
fish.appendChild(h);
}
console.log(onlineUsers)
});
});
//msg send
btn_send.addEventListener('click', function(){
socket.emit('send msg', msg_input.value);
});
//checks if enter is pressed, if so emits message to chat
function search(ele) {
if(event.key === 'Enter') {
socket.emit('send msg', msg_input.value);
}
}
//send message events
socket.on('send msg', function(data){
if(data.user == user){
//sender logic
msg_input.value = '';
let p = document.createElement('p');
receive_.append(p);
p.innerHTML = "<span class = 'er'>" + 'You' + "</span>" + ": " + data.msg;
p.style.textAlign = 'right';
p.style.backgroundColor = "#5cb85c";
p.style.justifyContent = "flex-end";
p.style.paddingRight = "2em";
}
else{
//receiver logic
msg_input.value = '';
let p = document.createElement('p');
receive_.append(p);
p.innerHTML = "<span class = 'er'>" + data.user + "</span>" + ": " + data.msg;
p.style.textAlign = 'left';
p.style.backgroundColor = "#5bc0de";
p.style.paddingLeft = "2em";
};
//makes sure scroll stays at bottom
receive_.scrollTop = receive_.scrollHeight;
});
function addAnimation(){
newUser_text.classList.add("act");
}
$( document ).ready(function(){
let header = document.querySelector(".feedback");
var timeout;
function timeoutFunction() {
typing = false;
socket.emit("typing", false);
}
$('#sendMsg').keyup(function() {
typing = true;
socket.emit('typing', 'typing...');
clearTimeout(timeout);
timeout = setTimeout(timeoutFunction, 5000);
});
socket.on('typing', function(data) {
if (data) {
$('#isTyping').html(data);
$('#isTyping').classList.add('act')
} else {
$('#isTyping').html("");
}
});
})
You should replace whole array on client side instead of push. Just stack trace your code:
Firstable on connection on server side you pushes new user id to usersOnline array and emits that array in object via USERS_CONNECTED event in usersOnline property. Client receives that object and pushes object of users (NOT exactly one new user) to onlineUsers array. So eg. 1 user connects to server, usersOnline array would be:
[ 'user1' ]
Then second user connects to server:
[ 'user1', 'user2' ]
And that array is being sent to user2, that is whole object sent by USERS_CONNECTED event would be:
{ usersOnline: [ 'user1', 'user2' ], user: 'user2' }
Now in client instead of replacing you are pushing whole new array, so instead [ 'user1', 'user2' ] you gets [ [ 'user1', 'user2' ] ]

Trying to save to Firebase database but getting undefined error

Hoping to get some help saving data to my Firebase database. I'm getting this error in the console "First argument contains undefined in property". Any help or advice solving this would be massively appreciated.
//Edit Profile
document.getElementById("profileSubmit").addEventListener('click', function(){
var user = firebase.auth().currentUser;
var name, email, photoUrl, uid;
if (user != null) {
name = user.displayName;
email = user.email;
photoUrl = user.photoURL;
uid = user.uid;
}
var username= document.getElementById("username");
var pathway= document.getElementById("pathway");
var avatar= document.getElementById("avatar");
if(username !== "" && pathway !== ""){
// Gets the users input
var getUsername = username.value;
var getPathway = pathway.value;
//var getAvatar = avatar.value;
var editRef= firebase.database().ref("Users/" );
editRef.child(uid).set({
DisplayName: getUsername,
Pathway: getPathway,
})
//Updates Firebase profile
user.updateProfile({
displayName: getUsername
})
$('#successBox').show();
$('#successBox').fadeOut(5000);
$('#username').val("");
$('#pathway').val("");
} //else {
// $('#errorBox').show();
//$('#errorBox').fadeOut(5000);
//}
});

Saving Javascript objects to Chrome.Storage

This code for a Google Chrome Extension doesn't work. I am new to Javascript and I am not sure what the problem is. Any help would be greatly appreciated.
JS/jQuery
var userV = serviceName + 'Username';
var passV = serviceName + 'Password';
boolean works = true;
var User = {
passV: password,
userV: username,
works = true;
}
chrome.storage.sync.set({User : userV}, function() {
console.log('');
});
chrome.storage.sync.set({User : passV }, function() {
console.log('');
});
Script
chrome.storage.sync.get("userV", function (User) {
sUsername = User.userV;
};
chrome.storage.sync.get("passV", function (User) {
sPassword = User.passV;
};
Thank you for any help.
In your code you are storing User and Password in the same Key Name hence you will get only Last assigned value,
as well as your retrieving the value by value not by key
JS/jQuery
var userV = serviceName + 'Username';
var passV = serviceName + 'Password';
boolean works = true;
var User = {
passV: password,
userV: username,
works = true;
}
chrome.storage.sync.set({User : userV}, function() {
console.log('');
});
chrome.storage.sync.set({Pass : passV }, function() {
console.log('');
});
Script
chrome.storage.sync.get("User", function (data) {
sUsername = data.User;
};
chrome.storage.sync.get("Pass", function (data) {
sPassword = data.Pass;
};
For more simplify, you can store the whole User object into the storage. When you want to store your user data, the code is like the following:
var userV = serviceName + 'Username';
var passV = serviceName + 'Password';
boolean worksV = true;
var user = {
password: passV,
username: userV,
works: worksV
};
chrome.storage.sync.set({"user" : user}, function() {
// Do something...
});
Then, when you want to retrieve the stored data, the code is:
chrome.storage.sync.get("user", function(data) {
var user = data.user;
var passV = user.password;
var userV = user.username;
var worksV = user.works;
// Do something...
});
I think that you don't need to store each data item as each property. I recommend that it will be stored as one object.

Handlebars.js - Combining Templates

Each section of my code below creates a new handlebars.js template to call the "User Behance API". As you can see, each section has similar code, with a variable or two difference.
Is there a way to clean up this code, and combine these separate functions into one? Just seems like a lot of code, but then again I am new to handlebars.
// BEHANCE API INFO ---
var apiKey = 'ZLBxK9rEfHwJf9K0rmseNr2fS2gS2HJW';
var userID = 'creativemints';
var perPage = 10;
var behanceUserAPI = 'http://www.behance.net/v2/users/' + userID + '?callback=?&api_key=' + apiKey;
var behanceProjectAPI = 'http://www.behance.net/v2/users/' + userID + '/projects?callback=?&api_key=' + apiKey + '&per_page=' + perPage;
// BEHANCE - USER HEADER ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userHead').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('header').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER ABOUT ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userAbout').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('.about').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER FOOTER ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userFoot').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('footer').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER COPYRIGHT ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userCopyright').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('#copyright').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
Haven't tested this but you should be able to simply the code to something similar to this
// BEHANCE API INFO ---
var apiKey = 'ZLBxK9rEfHwJf9K0rmseNr2fS2gS2HJW';
var userID = 'creativemints';
var perPage = 10;
var behanceUserAPI = 'http://www.behance.net/v2/users/' + userID + '?callback=?&api_key=' + apiKey;
var behanceProjectAPI = 'http://www.behance.net/v2/users/' + userID + '/projects?callback=?&api_key=' + apiKey + '&per_page=' + perPage;
// BEHANCE - USER HEADER ---
(function () {
function setUserTemplate(templateSelector, htmlSelector) {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $(templateSelector).html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$(htmlSelector).html(result);
}
if (!sessionStorage.getItem('behanceUser')) {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
});
}
setUserTemplate('#userHead','header');
setUserTemplate('#userAbout','.about');
setUserTemplate('#userFoot','footer');
setUserTemplate('#userCopyright','#copyright');
})();

Categories