How to check if the data was written to firebase database? [duplicate] - javascript

This question already has an answer here:
How to wait for firebase.database().ref('users/' + userId).set() to finish before calling next function?
(1 answer)
Closed 5 years ago.
I am using this code after submit is pressed to add data to my firebase database.
I want to redirect it to a new page after the data has been written, but I cannot figure out a way to check if data is written in database.
var email = document.getElementById("email");
var phone = document.getElementById("phone");
var details = document.getElementById("details");
function submit() {
if(!(email.value == null)) {
var storage = firebase.storage();
var ref = storage.ref();
var letters = ref.child('letters');
var userref = letters.child(email.value+".txt");
var data = details.value;
userref.putString(data);
var database = firebase.database();
var databaseref = database.ref().child("users");
databaseref.child(email.value).set({email: email.value,phone:phone.value},);
// tried this window.alert("https://google.com");
}
}

The below is example is from the firebase docs here:
adaNameRef.set({ first: 'Ada', last: 'Lovelace' })
.then(function() {
console.log('Synchronization succeeded');
})
.catch(function(error) {
console.log('Synchronization failed');
});
You can see that the .set method returns a firebase promise which will resolve if the data updated successfully and reject if it doesn't.
You should redirect in the same place that console.log('Synchronization succeeded'); is running in the example.

Related

How do I reject writing value to Firebase if have the same value in my DB? (Javascript)

I'm creating my custom order id with auto-increment generator function for my project. I will state my question here, if you want to know the whole story please read below.
As written in the title, I need a way to reject my set to Firebase and it has to be done in 1 query. Currently, it will write my orderID to Firebase without rejecting it. But I need to reject if there is the same ID in the table.
The short version of my code will be posted here, the whole function will be posted below.
firebase.database().ref('orderCounter/orderIDsChecker/'+orderID).set({
id: orderID,
}, function(error) {
if (error) {
console.log('Order ID fail to generate. Regenerating new ID')
createOrderID(orderCounterRef);
} else {
console.log('Order ID created!')
}
});
}
The story,
I'm creating my own custom order id with auto-increment generator function for my project. The problem is that if multiple users creating order at the same time, it will generate the same id. Yes, I can use transaction() to solve the problem but I have no idea how to use it. Therefore, I have created my own version of the "transaction". With my method, I am able to prevent duplicates id unless 2 or more users create order within 1 second of gap. Or if anyone is kind enough to show me an example of how to write a transaction for my function, I thank you in advance.
The flow of the code is,
Get "currentMonth" and "orderIdCounter" from Firebase -> orderIdCounter +1 and update to Firebase -> start the process of generating order id -> Send the generated id to firebase -> If return success "order ID created", If not "got duplicate id" Re-run the whole process.
Below is the code for my order id generator function.
function createOrderID(orderCounterRef){
var childData = [];
var orderID;
//Get the Current Month and Order ID Counter from Firebase
orderCounterRef.on('value', function(snap) { childData = snapshotToArrayWithoutID(snap); });
var currentMonth = childData[0];
var orderIDCounter = childData[1];
if (orderIDCounter !== undefined){
//Update orderIDCounter on Firebase.
//This is to prevent duplicate orderID when multiple users is creating order at the same time.
var IDCounter = parseInt(orderIDCounter) + 1;
//Set IDCounter to 3 digits
IDCounter = ('00' + IDCounter.toString()).slice(-3);
firebase.database().ref('orderCounter/orderIDCounter').set(IDCounter);
//Handle the process to generate Order ID. Return in YYMMxxx(auto increment) format.
orderID = handleCreateOrderID(currentMonth, (parseInt(orderIDCounter) - 1));
//Check if duplicate ID on firebase
firebase.database().ref('orderCounter/orderIDsChecker/'+orderID).set({
id: orderID,
}, function(error) {
if (error) {
console.log('Order ID fail to generate. Regenerating new ID')
createOrderID(orderCounterRef);
} else {
console.log('Order ID created!')
}
});
}
return orderID;
}
My DB:
You should indeed use a transaction as you have mentioned in your question.
The following should do the trick:
//Declare a function that increment a counter in a transaction
function createOrderID() {
var orderIdRef = firebase.database().ref('orderId');
return orderIdRef.transaction(function(currentId) {
return currentId + 1;
});
}
//Call the asynchronous createOrderID() function
createOrderID().then(function(transactionResult) {
console.log(transactionResult.snapshot.val());
});
If you want to start the counter at a specific value, just create an orderId node in your database and assign a specific value to it, e.g; 1912000.
If you just want to start at 1, you don't need to create a node, it will be automatically created with the first call to the createOrderID() function.
Thank you, #samthecodingman & #Renaud Tarnec for your advice.
I took #samthecodingman's code and change a bit to fit my project. But I use generateOrderID() only to call the result and it works well. But you won't get any value with just the code. I call out another function (connectToFirebase) whenever users enter the page. I am not sure why it works or if this is the right way, but it works for me and that's good enough.
export function generateOrderID(){
var orderId;
var childData = [];
const orderCounterRef = firebase.database().ref('orderCounter/');
//Get the Current Month from Firebase
orderCounterRef.on('value', function(snap) { childData = snapshotToArrayWithoutID(snap); });
//Check ID format YYMMXXX (XXX=auto_increment). Hanlde auto_increment for Year and Month
handleOrderIdFormat(childData[0], orderCounterRef)
//transaction
orderCounterRef.child('orderId').transaction(function(currentId) {
orderId = (currentId||0) +1;
return orderId;
}, function(err) {
if( err ) {
console.log(err)
}
});
return orderId;
}
export function connectToFirebase(){
//Connection Firebase Database
const orderCounterRef = firebase.database().ref('orderCounter/');
orderCounterRef.on('value', function(snap) { });
}

Window variables not accessible between Javascript files [duplicate]

This question already has answers here:
Persist variables between page loads
(4 answers)
Closed 3 years ago.
I have two javascript files to handle my webpage login function. First js file authenticates the user and returns a session token which should be passed to second js file for session validation.
Here is the snippet of first js file.
var Login = window.Login || {};
(function scopeWrapper($) {
var apiEndPoint = 'https://4pmsdffwl2.execute-api.ap-southeast-2.amazonaws.com/prod';
Login.sessionId = 'null'
function signin(username, password, onSuccess, onFailure) {
let endpoint = apiEndPoint + '/signin'
let config = {
"username": username,
"password": password
}
return axios.post(endpoint, config)
.then((res) => {
Login.sessionId = res.session_id
console.log(Login.sessionId) \\this prints the session id correctly
onSuccess(res);
return Promise.resolve('/')
})
.catch((err) => {
console.error(err)
onFailure(err)
return Promise.reject('/')
})
}
$(function onDocReady() {
$('#signinForm').submit(handleSignin);
});
function handleSignin(event) {
var email = $('#emailInputSignin').val().toLowerCase();
var username = email;
var password = $('#passwordInputSignin').val();
event.preventDefault();
signin(username, password, email,
function signinSuccess() {
console.log('Successfully Logged In');
window.location.href = 'second.html';
},
function signinError(err) {
alert(err);
}
);
}
}(jQuery));
The idea is to initiate a global variable sessionId which is updated with the session id by login function.
Here is the snippet of second js file where I'm trying to use the sessionId passed in from the first js file.
var Login = window.Login || {};
Login.map = Login.map || {};
(function uploadScopeWrapper($) {
console.log(Login.sessionId) \\This prints null instead of sessionId
if (Login.sessionId) {
window.location.href = 'welcome.html';
} else {
window.location.href = 'login.html';
}
}(jQuery));
I'm not quite sure why the window object is not getting updated with the sessionId that is being generated in signin function.
Sample code in plnkr here:
https://plnkr.co/bYECNY
Any help is much appreciated.
Thanks
You are navigating to a different page and then load the second script file from that different page.
All global variables are lost when you navigate to a different page, the same page or just refresh the current page.
For ways to store information longer than the current document is loaded into the browser, see Persist variables between page loads

Retrieve multiple data from firebase database in one cloud function

I am faced with the problem of retrieving two data values of a single node from my firebase database and reference it in my javascript file but don't know how to go about it. I have been able to retrieve just one data value from a node (in this case "message") but I would like to add "from" as well. Most tutorials just reference one so I am really confused. So how do I get multiple data values?
This is my code...
JS file
exports.sendNotification7 = functions.database.ref('/GroupChat/{Modules}/SDevtChat/{SDevtChatId}/message')
.onWrite(( change,context) =>{
// Grab the current value of what was written to the Realtime Database.
var eventSnapshot = change.after.val();
var str = "New message from System Development Group Chat: " + eventSnapshot;
console.log(eventSnapshot);
var topic = "Management.Information.System";
var payload = {
data: {
name: str,
click_action: "Student_SystemsDevt"
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(topic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
return;
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
You can read from however many nodes you want in a Cloud Function. However, only one can trigger the function to run.
To read from your database use the following code:
admin.database().ref('/your/path/here').once('value').then(function(snapshot) {
var value = snapshot.val();
});
You will probably want to read from the same place that the Cloud Function was triggered. Use context.params.PARAMETER to get this information. For the example you posted your code would turn out looking something like this:
admin.database().ref('/GroupChat/'+context.params.Modules+'/SDevtChat/'+context.params.SDevtChatId+'/from').once('value').then(function(snapshot) {
var value = snapshot.val();
});
Just trigger your function one level higher in the JSON:
exports.sendNotification7 =
functions.database.ref('/GroupChat/{Modules}/SDevtChat/{SDevtChatId}')
.onWrite(( change,context) =>{
// Grab the current value of what was written to the Realtime Database.
var eventSnapshot = change.after.val();
console.log(eventSnapshot);
var str = "New message from System Development Group Chat: " + eventSnapshot.message;
var from = eventSnapshot.from;
...

Checking data in deep array with includes (Firebase retrieve data JS)

So I am new to the Firebase database and what I like about it is that I don't have to build a whole backend for just storing some simple data. What I am trying to do is pushing data to an array that I like to recieve from firebase. Then after that I would like to check if the email that was filled in, is included in the data from the firebase database. But because it's firebase and it has multiple arrays, objects etc I don't know how to check that. So the flow is: User fills in data, Applications makes a call to the firebase db and the Application is retrieving the current data from firebase. Then the Application will check if the data that is inputed is already there, and if so, will throw an alert that the data is already in the database. If not, the data will be submitted.
Also, I am wondering if this is the right way to retrieve data from the database:
Main.js
function writeUserData() {
var name = document.getElementById("name").value;
var email = document.getElementById("email").value;
firebase.database().ref('/aanmeldingen/').push({
username: name,
email: email,
});
var dbRef = firebase.database().ref().child('/aanmeldingen/');
dbRef.on('value', snapshot => {
const snap = snapshot.val();
const array = [];
array.push(snap);
console.log(array);
const res = array.includes(email);
console.log(res);
console.log(email);
});
}
Output in console
As you can see this returns multiple data. The include function will check on the submitted emailadress. This returns false even I had inputted "info#webpack.com". How can I check the right data object? It has to check all objects under "0" and return in the console if the submitted emailadress is already there.
I haven't tested it yet but i hope you get the idea. Also this is not the most efficient way to do this.
function ifEmailExist(arr,email){
var _t = 0;
for(var x in arr){
for(var y in arr[x]){
if(arr[x][y].email){
if(arr[x][y] === email){
_t++;
}
}
}
}
return _t;
}
Usage:
if(ifEmailExist(arr,"info#webpack.com") > 0){
//do stuff
}
You should use child_added instead of value. Whenever a new node is added in database, child_added will trigger and then you can take action on the data.
var dbRef = firebase.database().ref().child('aanmeldingen');
dbRef.on('child_added', snapshot => {
var username = snapshot.val().username;
var email = snapshot.val().email;
console.log(username);
console.log(email);
});

Writing data to completely separate locations simultaneously using update()

In my firebase app when a new user signs up I add their initial data like displayname, emai , photourl to the database under the top level users node. This works fine.
Now when a user post a status, I want to upload the the post to top level statuses node where all user statuses are kept. And simultaneously I want to upload the post to current user's posts node i.e users/currentuser/posts.
I am following the methods shown on official firebase site here.
The problem is when I hit the post button nothing happens and no data is posted to the database
My function that gets invoked when the post button is clicked:
function postStatus(){
var ref = firebase.database().ref("allstatuses");
var user = firebase.auth().currentUser;
var newStatusRef = ref.push();
var newStatusKey = newStatusRef.key();
var statusData = {
status: postInput.val(),
likes: 0,
dislikes: 0
};
var updateUserStatus = {};
updateUserStatus["users/" + user.uid + "/" + newStatusKey] = statusData;
updateUserStatus["allstatuses/" + newStatusKey] = statusData;
if(user){
firebase.database().ref().update(updateUserStatus);
}else{
alert("please login");
}
}
What am I doing wrong?
According to the API reference link it is key not key()
Change this
var newStatusKey = newStatusRef.key();
to
var newStatusKey = newStatusRef.key;

Categories