JavaScript - Firebase value to global variable - javascript

ref.child("path").on("value", snapshot => {
var z = Object.keys(snapshot.val())[2];
y = snapshot.val()[z];
//Call the friggin thing
exportData(y);
function exportData(y) {
exporting(y);
}
});
function exporting(y) {
var x = y;
//console.log(y);
return x;
}
I want to store x in a global variable.
I cannot do code just below because 'y' will not be passed through.
'y' is a local variable.
var answer = exporting();
answer();

Storing the value in a global variable is not a problem, it's the when that is messing you up.
Data is loaded from Firebase asynchronously. This means that code doesn't run in the order that you probably expected. You can most easily see this by putting some logging in there:
console.log("Before starting to load value");
ref.child("path").on("value", snapshot => {
console.log("Loaded value");
});
console.log("After starting to load value");
When you run this code it prints:
Before starting to load value
After starting to load value
Loaded value
That is probably not the order you expected. But it explains perfectly why the global variable is not set when you access it: the value hasn't come back from the database yet.
That's why you'll want to move the code that needs the data from the database inside the callback function. Alternatively you can use the fact that once() returns a promise, which makes it easier to deal with as a result:
function loadData() {
return ref.child("path").once("value");
});
loadData().then((snapshot) => {
... use the data from snapshot
});
Note that is asynchronous loading is an incredibly common source of confusion for developers who are new to it. I highly recommend checking out some of the other questions on the topic:
How to return value from an asynchronous callback function?
How do I return the response from an asynchronous call?
How to get returned a value by a callback function
Return a value from a Firebase JS callback method (DAL) to another function (controller)
Firebase return output from function

I figured out a solution using jQuery
ref.child("path").on("value", snapshot => {
var y = Object.keys(snapshot.val())[2];
z = snapshot.val()[y];
$("#id").attr("data-stored", z);
updateVal();
});
var x;
function updateVal() {
x = parseFloat($("#id").attr("data-stored"));
}
console.log("It Works! " + x);

Related

Node.js using functions and callback

I am having some difficulties with node.js & using functions. My problem is when I call a function, node.js doesnt wait for it to finish and I ended up getting nothing as my return values. This is what I have
exports.handle = (event, context,callback) => {
switch (event.request.type)
{
case "IntentRequest":
console.log('INTENT REQUEST')
switch(event.request.intent.name)
{
case "MoveDown":
readpos()
}
}}
function readpos(){
var position = []
//this code parses an array and gets me x y values
return position }
My problem is I end up getting an empty array because node.js runs to fast. Im assuming I have to do something with callback but im unsure on how to implement callback. I've tried reading online tutorials on callback but all of them have confused me as well and I cant seem to apply what online resources say to my cold. My main language is c++ & Python.
It's quite simple. You handle it in your callback. Let's look at your fixed function:
exports.handle = (event, context,callback) => {
switch (event.request.type)
{
case "IntentRequest":
console.log('INTENT REQUEST');
switch(event.request.intent.name)
{
case "MoveDown":
callback(readpos());
}
}
};
function readpos() {
var position = [];
//this code parses an array and gets me x y values
return position;
}
And now, when you call the handle, you just call it as such:
handle(event, context,
// This is your callback function, which returns when done
function(position){
// When readPos() has run, it will return the value in this function
var newPos = position + 1; ...etc...
});
Of course, your code should follow conventions. Callbacks are designed to return errors and results so you should cater for that too. But this is just a general idea of callbacks :)
You need to use a callback as
exports.handle = (event, context,callback) => {
switch (event.request.type)
{
case "IntentRequest":
console.log('INTENT REQUEST')
switch(event.request.intent.name)
{
case "MoveDown":
callback();
}
}}
Usage
function readpos(){
var position = []
//this code parses an array and gets me x y values
Don't return here instead use the result directly or store into a global
}
handle(event,context,readpos);

Retrieve data from indexedDB and return value to function calling

I have share variable between javascript function which is asynchronous. One of them is main thread and another is event based. I want to return value when event is completed.
This is the code:
completeExecution = false; // Shared Variable (Global Variable)
indexDBdata = {}; // Shared Variable (Global Variable)
function getPermission(key) {
var permission_data={};
if(exist_in_local) {
indexdbConnection.getRecordByKey('userPermission',permitKey,function(data){
indexDBdata=data; // Before its complete function return value
});
} else {
// make ajax call & its working fine
}
return permission_data;
}
//get Data from IndexedDB
getRecordByKey:function(tableName,key,readRecords){
if(isEmptyOrNull(readRecords)){
console.log("callback function should not be empty");
return;
}
if(isEmptyOrNull(tableName)){
console.log("table name should not be empty");
return;
}
var returnObj={};
var isSuccessfull=false;
if(this.dbObject.objectStoreNames.contains(tableName)){
var transaction=this.dbObject.transaction(tableName);
var objectStore = transaction.objectStore(tableName);
objectStore.get(key).onsuccess = function(event) {
returnObj=event.target.result;
};
**//Return object after this events compelte**
transaction.oncomplete = function(evt) {
completeExecution=true;
indexDBdata=returnObj;
readRecords(returnObj);
};
transaction.onerror = function(evt) {
completeExecution=true;
indexDBdata={status:'404'};
readRecords("Table Not found");
};
} else {
completeExecution=true;
indexDBdata={status:'404'};
readRecords("Table Not found");
}
}
Problem is while retrieving data from indexedDB it always returns {} (empty object). I want to synchronised event thread and main thread or wait for event to be completed. I don't want to directly manipulate DOM on callbacks I have to return value.
If you have solution to above problem or any other trick then please help me.
Thanks in advance.
I don't find the question very clear, but if I understand it, then you need to learn more about writing asynchronous javascript. In general, functions that call callback functions are void (they return an undefined value). If you want to use the results of two callback functions together, then you will want to chain them so that upon the completion of the first function, which calls its callback function, the callback function then calls the second function which then calls the second callback. So there are four function calls involved. You will want to place the processing logic within the context of the successive callback function, instead of continuing the logic outside of the function and trying to use its return value.
In other words, instead of trying to do this:
function a() {}
function b() {}
var aresult = a();
var bresult = b(aresult);
// processing of both a and b
You would want to try and do something like following:
function a(acallback) {
acallback(...);
}
function b(bcallback) {
bcallback(...);
}
a(function(...) {
b(function(...) {
// all processing of both a and b
});
});

How do i use a value from a function in another as a callback? Node js

I´ve been making a prototype of webservice and I get confronted with the following problem: Whenever I try to use a 'var' as a callback i get: undefined.
What I'm tryng to do is:
var mysqlquery = function (){
var vAlue = XXX;
}
var service = function (pp, ee, cb){
var toReturn= ({ //XML code
Value: vAlue
})
cb(toReturn);
};
Output should be XXX
The service runs fine and logs the values, but when i try to make it a callback to respond it is undefined, I guess because of the async of node.
Already tried making it a global or global.window or calling it inside another function, none of wich work. I don´t want to use extra modules for this, is there any method for it ? (Also tried this.)
Any tip is much apreciated, thanks.
You already know that defining a var in a function limits its scope to that function, but you can pass that data out of the function using a return, like so:
var mysqlquery = function (){
return 'XXX';
}
console.log(mysqlquery())
> "XXX"
What's happening in the console.log line is that your function is being evaluated, and returns "XXX", and then it is passed to console.log.
This is the foundation of callbacks: if you have an asynchronous function, you can pass a callback function into it to feed in the result of the async function:
function print(res) {
console.log(res)
}
function asyncThing(cb) {
var ten = 5 + 5
window.setTimeout(cb.bind(this, ten), 5000)
}
asyncThing(print)
... [wait five seconds]...
> 10

json after success return undefined

I am using JS with Angular came to the following problem.
I am getting data from a requestService, so a call the request function and then do something with the data in a 'success' function. Inside this function, everything is fine and I get all my results but as soon as a leave the success function, my results are undefined. I read some other questions/answers about similar problems, and tried other things. However I do not really know how to hand this and wanted to ask this explicitly with a code example:
function loadShips() {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
console.log(Markers, '#1')
return Markers
});
console.log(Markers, '#2');
return Markers;
}
So anyone could maybe tell me, why Markers at the print out of '#1' are defined and at '#2' are undefined.
Assuming the request is being done asynchronously, the call at #2 is happening before the request's success method is being called. This would explain why the object does not exist yet.
One solution would be to pass a call back method into the factory as a parameter, and then call that method after the request success has occurred. That would look something like this:
function loadShips(callBack) {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
console.log(Markers, "#1");
callBack(Markers);
});
}
Using this method looks like this:
function myCallback(markers){
console.log(markers, "#2");
//assign markers to something
}
loadShips(myCallback);
As Will P pointed out, with asynchronous functions, the inline code after them will execute first, because the success function is still waiting in the event queue.
in addition to that, Markers is being returned from inside a anonymous function which will not return it as the result of loadShips but will return it inside ajax wonderland, never to be seen.
what you will have to do is have a function that receives the data when it is ready and call that function with the data. I'm assuming things happen after the ships load, those things will have to be called after the anonymous function is done creating Markers.
function loadShips() {
var count = 0;
RequestService.getShips(nelat, swlat, nelong, swlong, timestamp)
.success(function(results) {
var groupedShips = results.aisData.aisGroupedByShipType;
_.each(groupedShips, function(groupedShip) {
_.each(groupedShip, function(ship) {
Markers['marker' + count] = createMarker(ship);
count++;
});
});
doFancyWonderfulThingsInTheOcean(Markers);
});
}

Understanding closures: Constructing a meta-function that queues functions together

In terms of solving the problem, I have a fully working solution that I just finished here:
// synchronous dynamic script loading.
// takes an array of js url's to be loaded in that specific order.
// assembles an array of functions that are referenced more directly rather than
// using only nested closures. I couldn't get it going with the closures and gave up on it.
function js_load(resources, cb_done) {
var cb_list = []; // this is not space optimal but nobody gives a damn
array_each(resources, function(r, i) {
cb_list[i] = function() {
var x = document.body.appendChild(document.createElement('script'));
x.src = r;
console.log("loading "+r);
x.onload = function() {
console.log("js_load: loaded "+r);
if (i === resources.length-1) {
cb_done();
} else {
cb_list[i+1]();
}
};
};
});
cb_list[0]();
}
I am completely happy with this because it does what I want now, and is probably far easier to debug than what my first approach, if it had succeeded, would have been.
But what i can't get over is why I could never get it to work.
It looked something like this.
function js_load(resources, cb_done) {
var cur_cont = cb_done;
// So this is an iterative approach that makes a nested "function stack" where
// the inner functions are hidden inside the closures.
array_each_reverse(resources, function(r) {
// the stack of callbacks must be assembled in reverse order
var tmp_f = function() {
var x = document.body.appendChild(document.createElement('script'));
x.src = r;
console.log("loading "+r);
x.onload = function() { console.log("js_load: loaded "+r); cur_cont(); }; // TODO: get rid of this function creation once we know it works right
};
cur_cont = tmp_f; // Trying here to not make the function recursive. We're generating a closure with it inside. Doesn't seem to have worked :(
});
cur_cont();
}
It kept trying to call itself in an infinite loop, among other strange things, and it's really hard to identify which function a function is and what a function contains within it, during debugging.
I did not dig into the code, but it appears that jQuery.queue has also implemented a similar mechanism to my working one (using an array to track the queue of continuations) rather than using only closures.
My question is this: Is it possible to build a Javascript function that can take a function as argument, and enhance it with a list of other functions, by building closures that wrap functions it creates itself?
This is really hard to describe. But I'm sure somebody has a proper theory-backed mathematical term for it.
P.S. Referenced by the code above are these routines
// iterates through array (which as you know is a hash), via a for loop over integers
// f receives args (value, index)
function array_each(arr, f) {
var l = arr.length; // will die if you modify the array in the loop function. BEWARE
for (var i=0; i<l; ++i) {
f(arr[i], i);
}
}
function array_each_reverse(arr, f) {
var l = arr.length; // will die if you modify the array in the loop function. BEWARE
for (var i=l-1; i>=0; --i) {
f(arr[i], i);
}
}
The problem is how you were setting the value of cur_cont for every new function you made, and calling cur_cont in the onload callback. When you make a closure like tmp_f, any free variables like cur_cont are not 'frozen' to their current values. If cur_cont is changed at all, any reference to it from within tmp_f will refer to the new, updated value. As you are constantly changing cur_cont to be the new tmp_f function you have just made, the reference to the other functions are lost. Then, when cur_cont is executed and finishes, cur_cont is called again. This is exactly the same function that had just finished executing - hence the infinite loop!
In this sort of situation, where you need to keep the value of a free variable inside a closure, the easiest thing to do is to make a new function and call that with the value you want to keep. By calling this new function, a new variable is created just for that run, which will keep the value you need.
function js_load(resources, cb_done) {
var cur_cont = cb_done;
array_each_reverse(resources, function(r) {
// the stack of callbacks must be assembled in reverse order
// Make a new function, and pass the current value of the `cur_cont`
// variable to it, so we have the correct value in later executions.
// Within this function, use `done` instead of `cur_cont`;
cur_cont = (function(done) {
// Make a new function that calls `done` when it is finished, and return it.
// This function will become the new `cur_cont`.
return function() {
var x = document.body.appendChild(document.createElement('script'));
x.src = r;
console.log("loading "+r);
x.onload = function() {
console.log("js_load: loaded "+r);
done();
};
};
})(cur_cont);
});
// Start executing the function chain
cur_cont();
}
EDIT: Actually, this can be made even simpler by using the Array.reduce function. Conceptually, you are taking an array and producing a single function from that array, and each successive function generated should be dependant upon the last function generated. This is the problem that reduce was designed to help solve:
function js_load(resources, done) {
var queue = resources.reduceRight(function(done, r) {
return function() {
var x = document.body.appendChild(document.createElement('script'));
x.src = r;
console.log("loading "+r);
x.onload = function() {
console.log("js_load: loaded "+r);
done();
};
};
}, done);
queue();
};
Note that reduce and reduceRight are not available for older browsers (<= IE8). A JavaScript implementation can be found on the MDN page.

Categories

Resources