Trouble understanding doc().get() in firebase - javascript

I am having a bit of trouble understanding why my code is not working. I am trying to read data from firebase inside a react-native project. I can read it just fine, but I cannot set the data to any variables.
This is my code here.
let tmp;
let userRef = firebase.firestore().collection("Users");
userRef.doc(this.state.FirstName).get().then((document) => {
tmp = document.data().FirstName;
alert(tmp);
})
.catch((errorMsg) => {
alert(errorMsg);
})
alert("tmp Data: " + tmp);
};
The problem is that if I alert tmp inside of the function it shows the FirstName variable as expected. But when I alert tmp outside of the function, it shows undefined. I just cannot seem to wrap my head around why this is not working, if anyone could tell me what I'm doing wrong here, I would much appreciate it.

This is totally normal. It happens because if you put the alert outside the block, then it will get executed before the block, with tmp being uninitialized. The code that gets the FirstName from the database (the get() function) executes some code in another thread and your original thread continues without waiting for it to finish. When that another thread finishes execution, the code inside the block gets executed. You can verify this behavior by adding alerts before, inside, and after the block to see the order of the execution. To know more, read about asynchronous operations and promises.
Why all of this? Why does get() execute some code in another thread? Briefly, because it uses the network to access the Firebase database and it may take some time before getting a response back. If get() executes the 'networking code' in the same calling thread, then calling it from the main thread (the UI thread) will make your UI unresponsive until the response returns back. So, instead, get() dispatches the 'networking code' to another thread and returns a promise object immediately even before the 'networking code' finishes execution. You use that promise object to specify what you want to do with the result whenever it arrives. This way, the calling thread continues execution and does not need to wait, and in the case where the calling thread is the UI thread (which is usually the case), it means that your UI is always responsive.

Related

Dialogflow: setFollowupEvent not working inside 'then'

I made a chatbot which talks to an external API and calls another intent using the data provided by the API. The API provides the followup event's name. I have to make use of the inline editor only and not the webhook for certain reasons.
function setFollow(agent) {
agent.add("hello");
axios.post(url, body, {headers})
.then (({ data }) => {
agent.add("setting followup event");
agent.setFollowupEvent({ "name": data.followupEventInput_name, "parameters" : { "name": data.name}});
})
}
I am successfully calling the API and getting an appropriate response from it (the event name and the parameter value). The event and thus the next intent is still not being called. I even tried using hardcoded values to call the event but it did not work. The execution is going inside the then statement (checked with console logs) but the event is not being set (even with hardcoded values).
What is the reason behind this and how can I solve it?
I have already checked the contexts: there are 2 active contexts (A and B) and the intent which should be called based on the event has 1 input context (A). Right now, no intent is being triggered.
It was a JS issue. I was not returning the promise.
return axios.post(url, body, {headers}).then(...)
solved the issue.
This was happening because JavaScript code execution is asynchronous by default, which means that JavaScript won’t wait for a function to finish before executing the code below it. The return statement before the promise makes JS wait for the promise to resolve or reject.
Without the return statement, the function completed execution before agent.add() was executed and hence the Dialogflow bot was not working as expected.

Brython wait for image to load, ajax call, or other async functions to complete before continuing execution

How can Brython wait for an image to load similarly to how Jquery/Javascript does before proceeding with execution?
In the above Brython code errors list is never appended to because img.bind('load', on_load) does not block execution. How can I block execution before proceeding?
Feel free offer up suggestions or an alternative approach to dealing with waits/blocking in Brython.
error = []
img = html.IMG(src=blob)
document <= img
def on_load(event):
if img.height*img.width > 2:
errors.append(f"Image dimensions are too large.")
print(errors) # The above error does indeed exist in errors.
img.bind('load', on_load)
if errors:
print(errors) # errors is empty because this was declared as img.bind was running
Is there a place where you call img.load(), or is this supposed to happen automatically?
If not, then the current behaviour is expected because on_load() was declared and bound to img, but img's load() function is never called. Thus on_load() never actually runs.

Async/Await control flow in JavaScript/TypeScript in Node.js

Context: I'm trying to implement a rudimentary socket pool in TypeScript. My current implementation is just a list of sockets that have an "AVAILABLE/OCCUPIED" enum attached to them (it could be a boolean admittedly) that allows me to have a mutex-like mechanism to ensure each socket only sends/receives a single message at once.
What I understand: I got that Node.js's way of handling "parallel" operations is "single-threaded asynchrony".
What I infer: to me, this means that there is only a single "control pointer"/"code read-head"/"control flow position" at once, since there is a single thread. It seems to me that the readhead only ever jumps to somewhere else in the code when "await" is called, and the Promise I am "awaiting" cannot yet be resolved. But I am not sure that this is indeed the case.
What I am wondering: does "single-threaded asynchrony" ensure that there is indeed no jump of the control flow position at any other time than when "await" is called ? Or is there some underlying scheduler that may indeed cause jumps between tasks at random moments, like normal multithreading ?
My question: All of this to ask, do I need a pure mutex/compare-and-swap mechanism to ensure that my mutex-like AVAILABLE/OCCUPIED field is set appropriately ?
Consider the following code:
export enum TaskSocketStatus
{
AVAILABLE, //Alive and available
OCCUPIED, //Alive and running a task
}
export interface TaskSocket
{
status:TaskSocketStatus;
socket:CustomSocket;
}
export class Server //A gateway that acts like a client manager for an app needing to connect to another secure server
{
private sockets:TaskSocket[];
[...]
private async Borrow_Socket():Promise<TaskSocket|null>
{
for (const socket of this.sockets)
{
if (!socket.socket.Is_Connected())
{
await this.Socket_Close(socket);
continue;
}
if (socket.status === TaskSocketStatus.AVAILABLE)
{
//This line is where things could go wrong if the control flow jumped to another task;
//ie, where I'd need a mutex or compare-and-swap before setting the status
socket.status = TaskSocketStatus.OCCUPIED;
return (socket);
}
}
if (this.sockets.length < this.max_sockets)
{
const maybe_socket = await this.Socket_Create();
if (maybe_socket.isError())
{
return null;
}
//Probably here as well
maybe_socket.value.status = TaskSocketStatus.OCCUPIED;
return maybe_socket.value;
}
return null;
}
[...]
}
The issue I'm looking to avoid is two different "SendMessage" tasks borrowing the same socket because of race conditions. Maybe this is needless worry, but I'd like to make sure, as this is a potential issue that I would really prefer not to have to confront when the server is already in production...
Thanks for your help !
So, the control flow to another operation is not when await is called. It's when the running piece of Javascript returns back to the event loop and the event loop can then service the next waiting event. Resolved promises work via the event loop too (a special queue, but still in the event loop).
So, when you hit await, that doesn't immediately jump control somewhere else. It suspends further execution of that function and then causes the function to immediately return a promise and control continues with a promise being returned to the caller of the function. The caller's code continues to execute after receiving that promise. Only when the caller or the caller of the caller or the caller of the caller of the caller (depending upon how deep the call stack is) returns back to the event loop from whatever event started this whole chain of execution does the event loop get a chance to serve the next event and start a new chain of execution.
Some time later when the underlying asynchronous operation connected to that original await finishes it will insert an event into the event queue. When other Javascript execution returns control back to the event loop and this event gets to the start of the event queue, it will get executed and will resolve the promise that the await was waiting for. Only then does the code within the function after the await get a chance to run. When that async function that contained the await finally finishes it's internal execution, then the promise that was originally returned from the async function when that first await was hit will resolve and the caller will be notified that the promise it got back has been resolved (assuming it used either await or .then() on that promise).
So, there's no jumping of flow from one place to another. The current thread of Javascript execution returns control back to the event loop (by returning and unwinding its call stack) and the event loop can then serves the next waiting event and start a new chain of execution. Only when that chain of execution finishes and returns can the event loop go get the next event and start another chain of execution. In this way, there's just the one call stack frame going at a time.
In your code, I don't quite follow what you're concerned about. There is no pre-emptive switching in Javascript. If your function does an await, then its execution will be suspended at that point and other code can run before the promise gets resolved and it continues execution after the await. But, there's no pre-emptive switching that could change the context and run other code in this thread without your code calling some asynchronous operation and then continuing in the complete callback or after the await.
So, from a pure Javascript point of view, there's no worry between pure local Javascript statements that don't involve asynchronous operations. Those are guaranteed to be sequential and uninterrupted (we're assuming there's none of your code involved that uses shared memory and worker threads - which there is no sign of in the code you posted).
What I am wondering: does "single-threaded asynchrony" ensure that there is indeed no jump of the control flow position at any other time than when "await" is called ?
It ensures that there is no jump of the control flow position at any time except when you return back the event loop (unwind the call stack). It does not occur at await. await may lead to your function returning and may lead to the caller then returning back to the event loop while it waits for the returned promise to resolve, but it's important to understand that the control flow change only happens when the stack unwinds and returns control back to the event loop so the next event can be pulled from the event queue and processed.
Or is there some underlying scheduler that may indeed cause jumps between tasks at random moments, like normal multithreading ?
Assuming we're not talking about Worker Threads, there is no pre-emptive Javascript thread switching in nodejs. Execution to another piece of Javascript changes only when the current thread of Javascript returns back to the event loop.
My question: All of this to ask, do I need a pure mutex/compare-and-swap mechanism to ensure that my mutex-like AVAILABLE/OCCUPIED field is set appropriately ?
No, you do not need a mutex for that. There is no return back to the event loop between the test and set so they are guaranteed to be not interrupted by any other code.

Variable scope with jQuery and javascript

So, I wrote the following function:
function getData() {
var data;
$(function () {
$.getJSON('https://ipinfo.io', function (ipinfo) {
data = ipinfo;
console.log(data);
})
})
console.log(data);
}
The problem with the above is the 2nd console.log doesn't retain the info from the assignment inside the jQuery and logs an undefined object. I'm not exactly sure what is wrong, but I believe it to be something quite minor. However, as much as I've searched online, I haven't found an answer for this particular problem.
One line: Javascript is Asynchronous.
While many struggle to figure out what it exactly means, a simple example could possibly explain you that.
You request some data from a URL.
When the data from second URL is received, you wish to set a variable with the received data.
You wish to use this outside the request function's callback (after making the request).
For a conventional programmer, it is very hard to grasp that the order of execution in case of JavaScript will not be 1,2 and then 3 but rather 1,3,2.
Why this happens is because of Javascript's event-loop mechanism where each asynchronous action is tied with an event and callbacks are called only when the event occurs. Meanwhile, the code outside the callback function executes without holding on for the event to actually occur.
In your case:
var data;
$(function () {
$.getJSON('https://ipinfo.io', function (ipinfo) {//async function's callback
data = ipinfo;
console.log(data);//first console output
})
})
console.log(data);//second console output
While the async function's callback is executed when the data is received from the $.getJSON function, javascript proceeds further without waiting for the callback to assign the value to the data variable, causing you to log undefined in the console (which is the value of the data variable when you call console.log.
I hope I was able to explain that.!

Is there any possibility of two asynchronous Javascript function instances executing two blocks of code at the same time?

I understand that Javascript doesn't have multiple threads, but I'd like to know if the following code has any chance of breaking. My understanding is that unless an asynchronous function is called, such as setTimeout or an AJAX call, that once a block of code starts executing there's no way for it to pause until it completes or does call an asynchronous function.
Basically, users select multiple checkboxes and then hits a button that executes AJAX processing of their selections. My goal is to have a "Saving..." icon that stays only until all the AJAX processes are complete, and after all are finished display a success message.
Barring any AJAX errors, so long as the callback function in the jQuery.post executes in its entirety without interruption, I don't see how the if(numProcessed == toProcess) would ever execute more than once or less than once. But if two AJAX callbacks get into the callback function, both increment the numProcessed counter before either get to the following if, then it seems that the code inside would be executed twice.
var numProcessed = 0;
var checkedBoxes = jQuery("input[type=checkbox]:checked");
var toProcess = checkedBoxes.size();
checkedBoxes.each(function() {
jQuery.post('somepage.php',{...},function(results) {
numProcessed++;
if(numProcessed == toProcess) {
jQuery("#saving-message").remove();
jQuery("#feedback-panel").text('Successfully processed all selections.');
}
}
}
There is only one thread in JavaScript so every function that want to be execute is put in stack and have to wait until all others are execute. In your case "each" is the first function in the stack, so every callback function have to wait and will be execute in the order they put on the stack.
After all "numProcessed == toProcess" could only one time be true.
The rx.net team has introduced rx for javascript. Reactive extension are for asynchronous programming. they have also written for rxjs for jquery too. My be that suite your need http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

Categories

Resources