I am not an experienced developer and I have spent the last couple of days trying to understand few fundamental concepts about Javascript.
Single thread, blocking vs non-blocking and callback.
I have read a lot but I am still confused.
My understanding is that in a simple JS code all the statements are executed sequentially within a single thread.
In a more sophisticated situation where there are long running statements (db calls, network interaction, etc) this can be a huge problem.
The program execution (next statement) is BLOCKED until the current (long running) statement is completed.
Solution is to implement an asynchronous pattern, where the long running statement is executed in back ground (I can be brutally wrong here!) while the next statements are executed and when the long running statement has done, it passes back its result using a callback function provided in the calling statement.
Copy and pasting code from here and there I have written a trivial piece of code where I have a call back function
// function with callback
function doSomething(callback) {
callback();
}
// callback function implementation
function doSomethingElse() {
document.write("<p>Second element in the page</p>");
}
doSomething(doSomethingElse);
document.write("<p>First element in the page</p>");
The result of this code is actually what I would have expected before starting reading about non-blocking and callback (sequential code execution):
- Second element
- First element
So my question is, what's the magic fairy dust that transforms my code into asynchronous non-blocking one?
Cheers, Giovanni
what's the magic fairy dust that transforms my code into asynchronous non-blocking one?
In general, most long running operations will be handled APIs which handle asynchronous operations at a lower level than JavaScript (XMLHttpRequest for making HTTP requests being a prime example).
If you have need to implement a long running function yourself (maybe you want to do some heavy number crunching on the client) then you can use Web Workers.
var myWorker = new Worker("find_prime_numbers.js");
myWorker.onmessage = function(e) {
console.log('Next prime number is ' + e.data);
}
and in find_prime_numbers.js:
// Calculate some primes
postMessage(my_prime_number);
You have used callbacks, but it doesn't mean that this call is asynchronous.
It synchronously runs doSomething, which runs callback and outputs "Second element".
It would be asynchronous, if you had an asynchronous call there - AJAX call, file system access or a simple setTimeout:
function doSomething(callback) {
setTimeout(callback, 1000);
}
// callback function implementation
function doSomethingElse() {
document.write("<p>Second element in the page</p>");
}
doSomething(doSomethingElse);
document.write("<p>First element in the page</p>");
Now, it does the following: runs doSomething, which runs setTimeout and runs doSomethingElse right after that. At the same time, setTimeout asynchronously waits for 1 second and calls the function.
In other cases, it could be any other asynchronous operation, which requires time to complete.
Related
I am new to Javascript and Ascynchronous programming, and a few things confuse me, please point out the misfacts in my learning.
Callbacks of an Asynchronous function are put in a message queue and
executed via event loop.
Asynchronous execution is non-blocking, done
via event loop.
Functions like setTimeout are asynchronous.
Asynchronous functions are blocking, only their callbacks are
non-blocking.
If any of the above are wrong, please elaborate it.
Callbacks of an Asynchronous function are put in a message queue and executed via event loop.
No.
There are generally two kinds of asynchronous functions - ones that take some sort of callback to run when they are done and ones that produce a Promise as a result.
Callback-based functions
This is an example of a callback-based function:
setTimeout(() => console.log("foo"), 0);
console.log("bar");
/* output:
bar
foo
*/
setTimeout will delay a callback to be executed later. Even with a timeout of zero milliseconds, it still schedules the callback until after the current execution is complete, so the order is:
setTimeout schedules the callback.
console.log("bar") runs.
The callback with console.log("foo") runs.
There isn't a message queue, there is a queue of tasks to execute. As a brief overview, the event loop takes one task from the queueand executes it to completion, then takes the next one and executes it to completion, etc. A simple pseudo-code representation would be:
while(true) {
if (eventQueue.hasNext()) {
task = eventQueue.takeNext();
task();
}
}
See here for more information on the event loop.
With all that said, the event loop has more bearing on setTimeout than many other callback-based functions. Other examples of callback based functions are jQuery's $.ajax() or the Node.js fs module for file system access (the non-promise API for it). They, and others, also take a callback that will be executed later but the bounding factor is not the event loop but whatever underlying operation the function makes. In the case of $.ajax() when the callback would be called depends on network speed, latency, and the server which responds to the request. So, while the callback will be executed by the event loop, so is everything else. So, it's hardly special. Only setTimeout has a more special interaction here, since the timings might be imprecise based on what tasks are available - if you schedule something to run in 10ms and some task takes 12ms to finish, the callback scheduled by setTimeout will not run on time.
Promise-based functions
Here is an example:
async function fn(print) {
await "magic for now";
console.log(print);
}
fn("foo")
.then(() => console.log("bar"));
/* output:
foo
bar
*/
(I'm omitting a lot of details for now for illustration.)
Promises are technically an abstraction over callbacks tailored towards handling asynchronous operations. The .then() method of a promise takes a callback and will execute it after the promise gets resolved, which also happens after the asynchronous operation finishes. Thus, we can sequence together execution in the right order:
async function fn(print) {
await "magic for now";
console.log(print);
}
fn("foo");
console.log("bar");
/* output:
bar
foo
*/
In a way, promises are sort of callbacks because they are here to replace them and do it in broadly the same fashion. You still pass callbacks to be executed when something succeeds or fails. But they aren't just callbacks.
At any rate, a callback given to a promise is still delayed:
Promise.resolve()
.then(() => console.log("foo"));
console.log("bar");
/* output:
bar
foo
*/
But not via the same event queue as the one setTimeout uses. There are two queues:
macrotasks queue - setTimeout places things in it, and all UI interactions are also added here.
microtasks queue - promises schedule their things here.
When the event loop runs, the microtasks queue (so, promises) has the highest priority, then comes the macrotask queue. This leads to:
setTimeout(() => console.log("foo")); //3 - macrotask queue
Promise.resolve()
.then(() => console.log("bar")); //2 - microtask queue
console.log("baz"); //1 - current execution
/* output:
baz
bar
foo
*/
At any rate, I don't think I'm comfortable saying that promise-based functions work via callbacks. Sort of yes but in a reductionist sense.
Asynchronous execution is non-blocking, done via event loop.
No.
What is "blocking"?
First of all, let's make this clear - blocking behaviour is when the environment is busy executing something. Usually no other code can run during that execution. Hence, further code is blocked from running.
Let's take this code as example:
setTimeout(taskForLater, 5000);
while (somethingIsNotFinished()) {
tryToFinish();
}
Here taskForLater will be scheduled to run in 5 seconds. However, the while loop will block the execution. Since no other code will run, taskForLater might run in 10 seconds time, if that's how lot it takes for the loop to finish.
Running an asynchronous function doesn't always mean it runs in parallel with the current code. The environment executes one thing at time in most cases. There is no multi-threading by default in JavaScript, parallel execution is an opt-in behaviour, for example by using workers.
What is "asynchronous execution"?
This can mean a couple of things and it's not clear which one you reference:
Running through the body of an asynchronous function
Waiting until the underlying asynchronous operation is finished
In both cases the quoted statement is wrong but for different reasons.
The body of an async function
Async functions are syntactic sugar over promises. They use the same mechanism but just present the code differently. However, an async function is blocking. As a side note, so are promise executors (the callback given to a promise constructor). In both cases, the function will run and block until something causes it to pause. The easiest way to demonstrate it is with an async function - using await will pause the execution of the function and schedule the rest of it to be finished later.
Whole body is blocking:
async function fn() {
console.log("foo");
console.log("bar");
}
fn();
console.log("baz");
/* output:
foo
bar
baz
*/
Pausing in the middle:
async function fn() {
console.log("foo");
await "you can await any value";
console.log("bar");
}
fn();
console.log("baz");
/* output:
foo
baz
bar
*/
As a point of clarification, any value can be awaited, not just promises. Awaiting a non-promise will still pause and resume the execution but since there is nothing to wait for, this will cause it to be among the first things on the microtask queue.
At any rate, executing the body of an async function might block. Depends on what the operation is.
The underlying asynchronous operation
When talking about "underlying operation", most of the times we mean that we hand off the control to something else, for example the browser or a library. In this case, the operation is not fulfilled by the current JavaScript environment we call something which will perform an operation and only notify the current JavaScript environment when it finishes. For example, in a browser calling fetch will fire off a network request but it's the browser handling it, not our code. So it's non-blocking but not by outside the execution environment.
fetch("https://official-joke-api.appspot.com/random_joke")
.then(res => res.json())
.then(joke => console.log(joke.setup + "\n" + joke.punchline));
console.log("foo");
With that said, we cannot even generalise what a given asynchronous operation will do. It might actually block the execution, at least for a while, or it might be entirely carried out in a separate process to the current JavaScript environment.
Functions like setTimeout are asynchronous.
Yes.
Although, it's probably considering what is like setTimeout. Is it setInterval? Is it any callback-based asynchronous function? The problem is that the definition starts to become circular "asynchronous callback-based functions like setTimeout are asynchronous".
Not every function that takes a callback is asynchronous. Those that are might be considered similar to setTimeout.
Asynchronous functions are blocking, only their callbacks are non-blocking.
No.
As discussed above, asynchronous functions might block. Depends on what exactly they do. For example $.ajax will initiate a network request using the browser, similar to fetch. In the case of $.ajax the function blocks while preparing the request but not after it's sent.
The second problem with the statement is that it's incorrect to call the callbacks non-blocking - executing them will certainly block the execution again. The callback is a normal JavaScript code that will be executed via the event loop when its time comes. While the task is running to completion, execution is still blocked.
If you mean that they are non-blocking in the sense that the callback will be put on the event queue, that's still not guaranteed. Consider the following illustrative code:
function myAsyncFunction(callback) {
const asyncResult = someAsynchronousNonBlockingOperation();
doStuff(result);
callback(result);
doMoreStuff(result);
}
Once someAsynchronousNonBlockingOperation() produces a value executing callback will not be scheduled for later but will be part of the synchronous sequence of code that processes that result. So, callback will be executed later but it will not be a task by itself but part of an overall task that encompasses doStuff and doMoreStuff.
Callbacks of an Asynchronous function are put in a message queue and executed via event loop.
Just in a queue (no messages). By asynchronous function I suppose you mean Promises. Remember async and await are syntactic sugar for Promises. They are execute by the event loop.
Asynchronous execution is non-blocking, done via event loop.
Not really. Javascript is single threaded: whenever it starts executing your async code, it stays there as long as needed, unless you use Workers.
Functions like setTimeout are asynchronous.
Like Promise, setTimeout and similars put the callback in a queue, which will be executed somewhere in the event loop (which may behave different for each kind of async functions).
Asynchronous functions are blocking, only their callbacks are non-blocking.
Right!
I wanted to have a better understanding of how the event loop and asynchronous code works in Javascript. There is a ton of resources online but I could not find an answer to my question
Everyday I mostly use callbacks, promises, async/awaits, but at the end I am simply relying on already asynchronous methods.
Therefore I wanted to know how it works, creating an async function from scratch, and deal with blocking code (or should I say slow code, that is not an HttpRequest or anything that is already provided to us).
For example taking while loop with a very high condition to stop it, should take a second to finish. And this is what I decided to implement for my tests.
After my research, I could read that one way of making my code asynchronous, would be to use setTimeout with a 0ms delay (placing a message in the event queue, that will be executed after the next tick)
function longOperation(cb) {
setTimeout(function() {
var i = 0;
while (i != 1000000000) { i++; }
cb();
}, 0);
}
longOperation(() => {
console.log('callback finished');
})
console.log('start');
My question is:
When my code is finally going to be executed, why isn't it blocking anymore ? What is the difference between executing it normally, and placing a message that the event loop will pick to push it to the call stack ?
The following video shows how the event loop handles a setTimeout with 0 delay.
JavaScript Event loop with setTimeout 0
However, the code executed is a simple console log. In my example, this is a "long" operation...
The outer code executes to completion.
The setTimeout 0 timer expires immediately, so its callback runs right away and executes to completion (the long-running while loop and its callback).
During both of these code execution phases, no other JavaScript user code will run.
I have an async function that runs by a setInterval somewhere in my code. This function updates some cache in regular intervals.
I also have a different, synchronous function which needs to retrieve values - preferably from the cache, yet if it's a cache-miss, then from the data origins
(I realize making IO operations in a synchronous manner is ill-advised, but lets assume this is required in this case).
My problem is I'd like the synchronous function to be able to wait for a value from the async one, but it's not possible to use the await keyword inside a non-async function:
function syncFunc(key) {
if (!(key in cache)) {
await updateCacheForKey([key]);
}
}
async function updateCacheForKey(keys) {
// updates cache for given keys
...
}
Now, this can be easily circumvented by extracting the logic inside updateCacheForKey into a new synchronous function, and calling this new function from both existing functions.
My question is why absolutely prevent this use case in the first place? My only guess is that it has to do with "idiot-proofing", since in most cases, waiting on an async function from a synchronous one is wrong. But am I wrong to think it has its valid use cases at times?
(I think this is possible in C# as well by using Task.Wait, though I might be confusing things here).
My problem is I'd like the synchronous function to be able to wait for a value from the async one...
They can't, because:
JavaScript works on the basis of a "job queue" processed by a thread, where jobs have run-to-completion semantics, and
JavaScript doesn't really have asynchronous functions — even async functions are, under the covers, synchronous functions that return promises (details below)
The job queue (event loop) is conceptually quite simple: When something needs to be done (the initial execution of a script, an event handler callback, etc.), that work is put in the job queue. The thread servicing that job queue picks up the next pending job, runs it to completion, and then goes back for the next one. (It's more complicated than that, of course, but that's sufficient for our purposes.) So when a function gets called, it's called as part of the processing of a job, and jobs are always processed to completion before the next job can run.
Running to completion means that if the job called a function, that function has to return before the job is done. Jobs don't get suspended in the middle while the thread runs off to do something else. This makes code dramatically simpler to write correctly and reason about than if jobs could get suspended in the middle while something else happens. (Again it's more complicated than that, but again that's sufficient for our purposes here.)
So far so good. What's this about not really having asynchronous functions?!
Although we talk about "synchronous" vs. "asynchronous" functions, and even have an async keyword we can apply to functions, a function call is always synchronous in JavaScript. An async function is a function that synchronously returns a promise that the function's logic fulfills or rejects later, queuing callbacks the environment will call later.
Let's assume updateCacheForKey looks something like this:
async function updateCacheForKey(key) {
const value = await fetch(/*...*/);
cache[key] = value;
return value;
}
What that's really doing, under the covers, is (very roughly, not literally) this:
function updateCacheForKey(key) {
return fetch(/*...*/).then(result => {
const value = result;
cache[key] = value;
return value;
});
}
(I go into more detail on this in Chapter 9 of my recent book, JavaScript: The New Toys.)
It asks the browser to start the process of fetching the data, and registers a callback with it (via then) for the browser to call when the data comes back, and then it exits, returning the promise from then. The data isn't fetched yet, but updateCacheForKey is done. It has returned. It did its work synchronously.
Later, when the fetch completes, the browser queues a job to call that promise callback; when that job is picked up from the queue, the callback gets called, and its return value is used to resolve the promise then returned.
My question is why absolutely prevent this use case in the first place?
Let's see what that would look like:
The thread picks up a job and that job involves calling syncFunc, which calls updateCacheForKey. updateCacheForKey asks the browser to fetch the resource and returns its promise. Through the magic of this non-async await, we synchronously wait for that promise to be resolved, holding up the job.
At some point, the browser's network code finishes retrieving the resource and queues a job to call the promise callback we registered in updateCacheForKey.
Nothing happens, ever again. :-)
...because jobs have run-to-completion semantics, and the thread isn't allowed to pick up the next job until it completes the previous one. The thread isn't allowed to suspend the job that called syncFunc in the middle so it can go process the job that would resolve the promise.
That seems arbitrary, but again, the reason for it is that it makes it dramatically easier to write correct code and reason about what the code is doing.
But it does mean that a "synchronous" function can't wait for an "asynchronous" function to complete.
There's a lot of hand-waving of details and such above. If you want to get into the nitty-gritty of it, you can delve into the spec. Pack lots of provisions and warm clothes, you'll be some time. :-)
Jobs and Job Queues
Execution Contexts
Realms and Agents
You can call an async function from within a non-async function via an Immediately Invoked Function Expression (IIFE):
(async () => await updateCacheForKey([key]))();
And as applied to your example:
function syncFunc(key) {
if (!(key in cache)) {
(async () => await updateCacheForKey([key]))();
}
}
async function updateCacheForKey(keys) {
// updates cache for given keys
...
}
This shows how a function can be both sync and async, and how the Immediately Invoked Function Expression idiom is only immediate if the path through the function being called does synchronous things.
function test() {
console.log('Test before');
(async () => await print(0.3))();
console.log('Test between');
(async () => await print(0.7))();
console.log('Test after');
}
async function print(v) {
if(v<0.5)await sleep(5000);
else console.log('No sleep')
console.log(`Printing ${v}`);
}
function sleep(ms : number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
test();
(Based off of Ayyappa's code in a comment to another answer.)
The console.log looks like this:
16:53:00.804 Test before
16:53:00.804 Test between
16:53:00.804 No sleep
16:53:00.805 Printing 0.7
16:53:00.805 Test after
16:53:05.805 Printing 0.3
If you change the 0.7 to 0.4 everything runs async:
17:05:14.185 Test before
17:05:14.186 Test between
17:05:14.186 Test after
17:05:19.186 Printing 0.3
17:05:19.187 Printing 0.4
And if you change both numbers to be over 0.5, everything runs sync, and no promises get created at all:
17:06:56.504 Test before
17:06:56.504 No sleep
17:06:56.505 Printing 0.6
17:06:56.505 Test between
17:06:56.505 No sleep
17:06:56.505 Printing 0.7
17:06:56.505 Test after
This does suggest an answer to the original question, though. You could have a function like this (disclaimer: untested nodeJS code):
const cache = {}
async getData(key, forceSync){
if(cache.hasOwnProperty(key))return cache[key] //Runs sync
if(forceSync){ //Runs sync
const value = fs.readFileSync(`${key}.txt`)
cache[key] = value
return value
}
//If we reach here, the code will run async
const value = await fsPromises.readFile(`${key}.txt`)
cache[key] = value
return value
}
Now, this can be easily circumvented by extracting the logic inside updateCacheForKey into a new synchronous function, and calling this new function from both existing functions.
T.J. Crowder explains the semantics of async functions in JavaScript perfectly. But in my opinion the paragraph above deserves more discussion. Depending on what updateCacheForKey does, it may not be possible to extract its logic into a synchronous function because, in JavaScript, some things can only be done asynchronously. For example there is no way to perform a network request and wait for its response synchronously. If updateCacheForKey relies on a server response, it can't be turned into a synchronous function.
It was true even before the advent of asynchronous functions and promises: XMLHttpRequest, for instance, gets a callback and calls it when the response is ready. There's no way of obtaining a response synchronously. Promises are just an abstraction layer on callbacks and asynchronous functions are just an abstraction layer on promises.
Now this could have been done differently. And it is in some environments:
In PHP, pretty much everything is synchronous. You send a request with curl and your script blocks until it gets a response.
Node.js has synchronous versions of its file system calls (readFileSync, writeFileSync etc.) which block until the operation completes.
Even plain old browser JavaScript has alert and friends (confirm, prompt) which block until the user dismisses the modal dialog.
This demonstrates that the designers of the JavaScript language could have opted for synchronous versions of XMLHttpRequest, fetch etc. Why didn't they?
[W]hy absolutely prevent this use case in the first place?
This is a design decision.
alert, for instance, prevents the user from interacting with the rest of the page because JavaScript is single threaded and the one and only thread of execution is blocked until the alert call completes. Therefore there's no way to execute event handlers, which means no way to become interactive. If there was a syncFetch function, it would block the user from doing anything until the network request completes, which can potentially take minutes, even hours or days.
This is clearly against the nature of the interactive environment we call the "web". alert was a mistake in retrospect and it should not be used except under very few circumstances.
The only alternative would be to allow multithreading in JavaScript which is notoriously difficult to write correct programs with. Are you having trouble wrapping your head around asynchronous functions? Try semaphores!
It is possible to add a good old .then() to the async function and it will work.
Should consider though instead of doing that, changing your current regular function to async one, and all the way up the call stack until returned promise is not needed, i.e. there's no work to be done with the value returned from async function. In which case it actually CAN be called from a synchronous one.
i have a little problem in understand of callbacks. I have read a lot in the last 2 days and what i have understand is the following (correct me, if i'm wrong):
JavaScript is a single thread language and you can program synchronous and asynchronous.
Synchronous means, each statement waits for the previous statement to finish before executing. That can lead into trouble, because if for instance a connection to a database needs a lot of time, the statements after the previous has to wait.
Finally that's very bad and that's why it's better to program asynchronous in Javascript, because Asynchronous code doesn't have to wait, the code can continue to run and the user don't have to wait.
To program asynchronous the Callbacks (functions of higher order) are needed.
Now i have try to program a little example by a lot of tutorials, etc.
function testCallback(a,callback){
console.log('1.function and given parameter: '+a);
callback(10);
}
testCallback(5 , function(x){
console.log("2.function and given parameter of 1. function: "+x);
});
Is that right? the output is:
1.function and given parameter: 5
2.function and given parameter of 1. function: 10
I do not understand, what the advantage is of this code, because i think that can still lead into trouble? If "console.log('1.function and....') has problems, the callback(10) function would even stop or not?
Thanks for any help!
JavaScript is a single thread language...
No, it isn't. The language says nothing about threading. Most environments give you a single thread per global environment, though (and on browsers you can create more, which interoperate through messaging). NodeJS provides just the one thread. Some environments (such as Rhino or Nashorn on the JDK) provide true multi-threading (and all the advantages and hassles that can involve).
Using a callback doesn't make code asynchronous. Your example, for instance, is not asynchronous. Consider:
function testCallback(a,callback){
console.log('1.function and given parameter: '+a);
callback(10);
}
console.log("Before the call");
testCallback(5 , function(x){
console.log("2.function and given parameter of 1. function: "+x);
});
console.log("After the call");
Note how we don't see After the call until after 2.function and given parameter of 1. function: 10. If the callback were asynchronous, we'd see it before:
function testCallback(a,callback){
console.log('1.function and given parameter: '+a);
setTimeout(function() { // Using setTimeout
callback(10); // to make this call
}, 0); // asynchronous
}
console.log("Before the call");
testCallback(5 , function(x){
console.log("2.function and given parameter of 1. function: "+x);
});
console.log("After the call");
Whether a callback is called synchronously or asynchronously depends entirely on what the function you're passing it to does. For instance, the callback used by Array#sort is called synchronously, but the callback used by setTimeout is called asynchronously.
For code to be asynchronous, it has to start an operation and then have that operation complete later, triggering a callback. setTimeout does that, as does ajax when used correctly, as do a wide range of other things.
Note that callbacks are currently how you handle asynchronous behavior (simple callbacks like the above, or promise callbacks), but the next specification (ES2017) will define built-in language semantics for dealing with asynchronousity without callbacks in the form of async and await. You can use that syntax today if you transpile with a tool like Babel.
In javascript callbacks can be synchronous or asynchronous. Synchronous callbacks can have a lot of benefits, but they don't do anything to stop your code blocking.
I think the best way to understand what asynchronous code is, and why it's beneficial, is to learn how Javascript actually evaluates your code. I recommend this video, which explains the process very clearly https://www.youtube.com/watch?v=8aGhZQkoFbQ
A JavaScript Callback Function is a function that is passed as a parameter to another JavaScript function. Callbacks can be synchronous or asynchronous. Simply passing a function as parameter will not change its current behavior.
It's behavior can be changed by the method which will execute it by calling it inside an event listener or setTimeout function etc. Basically event listener or setTimeout etc are handled by webapi in async fashion. If callback functions are inside these functions then these are moved to a queue by webapi when they are activated like button click(event listener) or time declared in setTimeout passed. They will move from queue to stack(if stack is empty) and run on stack finally.
The main advantage of using callback function can be seen from below code :-
var add = function(x,y) {
return x+y;
}
var multiply = function(x,y){
return x*y;
}
var calculate = function(x,y,callback){
return callback(x,y);
}
console.log(calculate(4,9,add));
Here is my code
var x = 0
data.results[0].taxonomies.some(function(e){
if(taxo.indexOf(e.code)!=-1){ //if at least one code from the data base is in my list of codes
callback(validLic(data.results[0].taxonomies)) //return true after some other validations
return true
}else{
x++
return false
}
})
if(x==data.results[0].taxonomies.length){callback(false)}//if the entire array was processed, and I didn't find anything I was looking for, return false
I'd like someone to confirm that due the async nature of node, the last if statement is at some point, bound to fire off before I'm done processing the array.
How can I better manage this situation without the help of some sync or parallel library?
The reason I ask it that way is because I'm under the impression that if I can't write something to be completely async, then I'm not writing it efficiently, right?
EDIT:
Based on Luc Hendirks' logic, I have changed my code to this:
var flag = data.results[0].taxonomies.some(function(e){
if(taxo.indexOf(e.code)!=-1){ //if at least one code from the data base is in my list of codes
return true
}else{
return false
}
})
if(flag==true){
callback(validLic(data.results[0].taxonomies))
}else{
callback(false)
}
Because this follows the sync traits outlined below, I shouldn't have an issue with flag being undefined before the callback is called now right?
Javascript (and Node) are single threaded, meaning it has only 1 CPU available. If the functions you call only require CPU time, making it async is useless. If you need to call a function and the CPU has to wait (do nothing), then making it async is very useful. Because while it is waiting until the function is finished it can do something else.
A function that checks if a url is valid with a regular expression can be synchronous, as the CPU needs to do some calculations and you get the result. If the function actually does a GET request and checks the response code, the CPU has to wait until the response is received. In the meantime it could do something else, so this function should be made asynchronous.
The difference of a synchronous and asynchronous function is that a synchronous function returns a value:
function(a) { return a; }
and an asynchronous function returns the result using a callback function (this is an actual function that you put in as a function argument):
function(callback){
// Do something that takes time but not CPU, like an API call...
callback('Some result');
}
A synchronous function is called like this:
var a = something();
Asynchronous like this:
something(function(result){
console.log(result);
});
So to answer your question, if some() is an asynchronous function, then the last if statement can be executed before the some function is finished. Because: the CPU does not want to wait. It can do other stuff while waiting. That's the power of asynchronous programming. t
It is also important to know that "parallel" does not exist in Javascript/Node. There is only 'doing stuff instead of waiting', like executing multiple API calls at the same time. That is not parallel computing as in using multiple threads.
Here is some more info: What is the difference between synchronous and asynchronous programming (in node.js)