How to understand JavaScript synchronicity/asynchronicity - javascript

The other day, I wrote this function in JavaScript as a simple DTO for an object from a jQuery plugin. I assumed that if I wrote a general return gridColumns line at the end of the function, the array could possibly be returned before my for loop was finished populating it. So I wrote this while (true) statement at the end, thinking I was being clever.
function getGridColumns() {
var gridColumns = [];
var records = $("#jqxGrid").jqxGrid("columns").records;
for (var i = 0; i < (records.length); i++) {
var obj = {
datafield: records[i].datafield,
width: records[i].width,
cellsalign: records[i].cellsalign,
hidden: records[i].hidden
}
gridColumns.push(obj);
}
while (true) {
if (gridColumns.length == records.length {
return gridColumns;
}
}
};
A buddy of mine looked at my little "hack" and said it was completely unnecessary, and I did some testing and determined that he's right.
So, here's where I'm at. How is JavaScript asynchronous, and how is it not? Can anyone help me understand this paradigm so that I can write better JavaScript?

The most common mechanisms that spawn new "threads" of execution and thus so to speak introduce an asynchronous situation in javascript are AJAX call callbacks (unless the call was specifically made synchrounous) and setInterval() and setTimeout() calls. As pointed out by Pointy, there are more than this though.

Related

Is it more performant to use several for-loops by themself or to delegated the logic to promises?

Following scenario: A function gets 3 arrays of a certain length, each one of those needs to be iterated over to find a matching object. When the object is found, the for-loop breaks and the next one isn't called. The arrays can't be merged in this case. Basically like this:
for (let i = 0; i < array1.length; i++) {
if (array1[i].id == matchingID) {
returnValue = array1[i];
break;
}
}
if (!returnValue) {
for (let i = 0; i < array2.length; i++) {
if (array2[i].id == matchingID) {
returnValue = array2[i];
break;
}
}
}
if (!returnValue) {
for (let i = 0; i < array3.length; i++) {
if (array3[i].id == matchingID) {
returnValue = array3[i];
break;
}
}
}
return returnValue;
Would using promises be more efficient in this case, since that way all for-loops can be worked at at the same time? Like this, with each function-call doing one of the for-loops (and resolving the found value) from the example above:
return new Promise((resolve) => {
this.findMatchingIDInArray1(array1)
.then(() => resolve(returnValue));
this.findMatchingIDInArray2(array2)
.then(() => resolve(returnValue));
this.findMatchingIDInArray3(array3)
.then(() => resolve(returnValue));
})
Which way is more perfomant? Is there better way to do this? Thanks for your help!
Would using promises be more efficient in this case, since that way all for-loops can be worked at at the same time?
No, you misunderstood what promises do. They're a tool to make dealing with asynchronous code easier. There is no asynchronous code in your use case, so you cannot make use of promises here. Promises do not "make" anything asynchronous, or even enable multithreading-like parallelism.
Would using promises be more efficient in this case, since that way all for-loops can be worked at at the same time?
No, because promises don't make anything asynchronous or parallel. They can only be used to observe things that are already asynchronous or parallel.
All that throwing promises at that code would do is change when the main thread blocks and add overhead.
If you need to offload or parallelize long-running computational tasks, look at web workers.
The code would not be any more performant.
JavaScript is typically single-threaded (unless you use web workers), so your code wouldn't complete any more quickly using promises (because the loops wouldn't run in parallel)—in fact, if anything, it might be imperceptibly slower.
A promise is more of a way to handle the outcome of asynchronous code, and not a way to cause code to run asynchronously.

Issues with promise inside for loop [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
I am trying to call a promise inside a for loop. I need the call to have the relevant loop item. I read a bit about it but still can't seem to figure the correct way to do it.
var params;
var identifylayers =["parcels", "lots", "gasstation"];
for (i = 0; i < identifylayers.length; i++)
{
lname = identifylayers[i];
govmap.intersectFeatures()
.then(function (e)
{
alert( lname);
});
}
Running the function returns: gasstation,gasstation,gasstation
I want it to return: parcels, lots, gasstation
What am I doing wrong?
Its the async devil of JavaScript lurking in your code. :D
Observe it like this -
As soon as your program flow encounter a promise call which here is - intersectFeatures().then(fn (){}), it know that this call will eventually finish so the program flow will never attempt to execute the callback passed to .then() right at the moment instead it will keep it safe with itself and set a reminder that as soon as the intersectFeatures is finished it need to execute the callback passed to .then().
Next thing to notice is how the .then(callback) will have access to lname. Its by closures. So
Another important thing to notice is that this whole stuff is inside a loop. Your loop has no idea whether the code its iterating on is synchronous or asynchronous. Its only task is to iterate. And as we mentioned before in Point - 1 the .then(callback) will not be executed right at the moment. So by the time then .then(callback) will be executed your loop would already be finished and at the end of iteration lname holds gasstation. Hence your .then(callback) only print gasstation
Solution:
This is really old JS solution of iterating the async code and still ensuring the proper variable access using closures -
for (i = 0; i < identifylayers.length; i++)
{
lname = identifylayers[i];
(function (lname) {
govmap.intersectFeatures()
.then( function () {
alert(lname);
} )
})(lname);
}
This utilises the benefit of functional scope of a variable and idea of closures. Google it to find more information.
Its also referred to as befriending closures, I just made that up :D
Cheers!
Define lname in the loop. Currently it is the same instance for each iteration, so it gets overriden, and then the promise resolves and prints the last overwrite each time.
const lname = identifylayers[i];
It is getting overriden before the async code runs.
async function intersectFeatures() {
return "OK"
}
var params;
var identifylayers = ["parcels", "lots", "gasstation"];
for (let i = 0; i < identifylayers.length; i++) {
const lname = identifylayers[i];
intersectFeatures()
.then(function(e) {
alert(lname);
});
}

Is this is a valid pattern and what is it called?

I find myself writing the following JavaScript more and more and I would like to know if this is a common pattern and if so, what is it called?
Part of the code and pattern:
var fruits = ["pear", "apple", "banana"];
var getNextFruit = function() {
var _index = 0,
_numberOfFruits = fruits.length;
getNextFruit = function() {
render(fruits[_index]);
_index = (_index + 1) % _numberOfFruits;
}
getNextFruit();
};
I have a function which takes no parameters, inside the function I redefine the function and immediately call it. In a functional language this might be a function being returned, JavaScript just makes it easier because you can reuse the name of the function. Thus you are able to extend the functionality without having to change your implementation.
I can also imagine this pattern to be very useful for memoization where your "cache" is the state we wrap around.
I even sometimes implement this with a get or a set method on the function where I can get the state if it's meaningful. The added fiddle shows an example of this.
Because this is a primarily JavaScript oriented question: The obligatory fiddle
I have a function which takes no parameters, inside the function I redefine the function and immediately call it.
Is this is a valid pattern and what is it called?
A function redefining itself is usually an antipattern, as it complicates stuff a lot. Yes, it sometimes can be more efficient to swap out the whole function than to put an if (alreadyInitialised) condition inside the function, but it's very rarely worth it. When you need to optimise performance, you can try and benchmark both approaches, but otherwise the advice is to keep it as simple as you can.
The pattern "initialises itself on the first call" is known as laziness for pure computations (in functional programming) and as a singleton for objects (in OOP).
However, most of the time there's no reason to defer the initialisation of the object/function/module whatever until it is used for the first time. The ressources taken for it (both time and memory) are insignificant, especially when you are sure that you will need it in your program at least once. For that, use an IIFE in JavaScript, which is also known as the module pattern when creating an object.
Creating a function via a closure is a pretty common pattern in JavaScript. I would personally do that differently:
var fruits = ["pear", "apple", "banana"];
var getNextFruit = function(fruits) {
var index = 0,
numberOfFruits = fruits.length;
function getNextFruit() {
render(fruits[_index]);
index = (_index + 1) % numberOfFruits;
}
return getNextFruit;
}(fruits);
There's no good reason (in my opinion) to clutter up the variable names with leading underscores because they're private to the closure anyway. The above also does not couple the workings of the closure with the external variable name. My version can be made a reusable service:
function fruitGetter(fruits) {
var index = 0, numberOfFruits = fruits.length;
function getNextFruit() {
render(fruits[_index]);
index = (_index + 1) % numberOfFruits;
}
return getNextFruit;
}
// ...
var getNextFruit = fruitGetter(someFruits);
var otherFruits = fruitGetter(["kumquat", "lychee", "mango"]);

Javascript Closure Within a For Loop (2 closures involved - an $http.get call and a $scope.$watch) using angular.js

I'm creating an angular app using angular-google-maps. What I'm trying to do is loop through an array of locations in order to place a marker at each location's latitude and longitude. However, because I'm using a couple of closures within my for-loop, a marker is only showing up at the last entry of the array. Here's the code:
$scope.petMarkers = [];
$http.get('/api/pets').success(function(foundPets){
$scope.foundPets = foundPets;
var listOfPets = $scope.foundPets;
var markerCreator = function(arrayOfPets){
for (var i = 0; i < arrayOfPets.length; i++){
var singlePet = arrayOfPets[i];
var petName = arrayOfPets[i].name;
var identity = singlePet._id;
var location = singlePet.addressFound;
var split = location.split(' ');
var joined = split.join('+');
var httpAddress = 'http://maps.google.com/maps/api/geocode/json?address=' + joined + '&sensor=false';
// anonymous function keeps reference to i, and when console.log is called, for loop has already finished and value of i is set to 4
$http.get(httpAddress).success(function(mapDataAgain){
var ladder = mapDataAgain.results[0].geometry.location.lat;
var longer = mapDataAgain.results[0].geometry.location.lng;
var obj = {
latitude: ladder,
longitude: longer,
title: petName,
id: i
};
$scope.$watch(function(){
console.log('we are in scope.watch');
return $scope.map.bounds;
}, function(){
var markers = [];
//markers.push(obj);
$scope.petMarkers.push(obj);
//$scope.petMarkers = markers;
console.log('markers = ', $scope.petMarkers);
}, true);
});
};
};
markerCreator(listOfPets);
});
Any ideas as to how to use an immediately invoked function expression(IIFE) with this code? I'm having trouble figuring out whether I need two IIFEs (one for the anonymous function called upon success of the $http call and one for the anonymous function called as the argument to $scope.$watch). I'm kind of lost here, so any explanation/help/suggestions would be helpful.
You don't need a for loop, and you certainly don't need an IIFE. You have an array of results, so just call the native .forEach function. It takes a callback that can is executed on all elements in the array. Benefits of this approach:
Gives you closure by default. The callback has its own scope and in a way is self-contained and separate from other code. Each element will get its own marker
Makes your code much easier to read. This is a much too often overlooked detail in coding. You want to strive to avoid any sort of technical debt—one of the easiest ways to do this is use the native array methods. They clearly communicate your code's intentions & makes debugging a lot easier (esp. necessary when asking for help, say on stack overflow, as it takes a lot of time and not many people want to help you if they can't make sense of your code)

In Javascript, what's better than try/catch for exiting an outer scope?

In Javascript, I sometimes want to return a value from a scope that isn't the current function. It might be a block of code within the function, or it might be an enclosing function as in the following example, which uses a local function to recursively search for something. As soon as it finds a solution, the search is done and the outer function should just exit. Unfortunately, I can't think of a simpler way to do this than by hacking try/catch for the purpose:
function solve(searchSpace) {
var search = function (stuff) {
var solution = isItSolved(stuff);
if (solution) {
throw solution;
} else {
search(narrowThisWay(stuff));
search(narrowThatWay(stuff));
};
};
try {
return search(searchSpace);
} catch (solution) {
return solution;
};
};
I realize one could assign the solution to a local variable and then check it before making another recursive call, but my question is specifically about transfer of control. Is there a better way than the above? Perhaps involving label/break?
Edit: since the answers to date are variations of "ew that's bad
you're not supposed to do that", let me add some necessary
context. I'm hacking on an open-source compiler that targets
Javascript. No one is going to write this code by hand, so please
don't tell me "this is a bad programming technique". What I want is a
better code generation technique. The question is whether anyone has
any clever hack for exploiting Javascript to get more flexible control
transfer.
The reason assigning the result to a local variable and checking it is
ruled out is because that requires understanding the code in a way
that is hard for a compiler to do.
It seems I stand corrected on the intent of the question. If statements are are a useful and readable way to structure code and make it flow however you want to. There's a reason goto was taken out of so many languages, because you don't need it. And it seems like, based on your example code, you're using a try-catch block as a form of goto. If you don't want certain things to run then use if statements or equivalents:
function solve(searchSpace) {
function search = function (stuff) {
//|| will only return the first value if that value is truthy, subsequent values will be ignored
return isItSolved(stuff) || (search(narrowThisWay(stuff)) || search(narrowThatWay(stuff)));
};
return search(searchSpace);
};
I know of no way to break out of function calls like you want. You can break out of loops using labels, but it doesn't seem that's much help to your situation. Other than that, I don't think JavaScript has any such ability beyond your use of exceptions
function solve(stuff) {
return isItSolved(stuff) || solve(narrowThisWay(stuff)) || solve(narrowThatWay(stuff));
}
Bob's way is good... exept that he uses twice the function statement (and that he uses ; after a function delaration without an assignment)... and that as we can do it that way, function solve actually is function search.
PS : This code will epically fail if the isItSolved, narrowThisWay or narrowThatWay functions can return a value evaluated to false as a positive result. In this cas, you would have to use ? : statement in order to check if all responses are !== undefined.
PS2: And of ourse, if these function can send an error, you have to catch it...
It looks like you're doing a fairly straightforward recursive search in your example. Why not just use "return"?
function solve(searchSpace) {
var search = function (stuff) {
var solution = isItSolved(stuff);
if (solution) {
return solution;
} else {
solution = search(narrowThisWay(stuff));
if (solution) {
return solution;
}
return search(narrowThatWay(stuff));
};
};
return search(searchSpace);
};
I suppose it could be that there are other constraints you haven't mentioned, but it's in general possible to turn any control flow into a set of nested (or recursive) functions, with appropriate return values.
The cleanest way would be to use a continuation, but you don't have that efficiently in JS (a few JS engines support continuations, but for the rest there's only CPS, which cries out for tail calls). In C, you could use setjmp/longjmp. In Common Lisp, you could use conditions (which include the functionality of exceptions plus much more). In JS, exceptions are the only non-local control flow option you have available.
You can programmatically transform a program into another that uses CPS.
function solve(searchSpace, isItSolved, isBase, narrowThisWay, narrowThatWay) {
function search(stuff, k) {
solution = isItSolved(stuff);
if (solution) {
return solution;
} else if (isBase(stuff)) {
return k();
} else {
return search(narrowThisWay(stuff), function() {
return search(narrowThatWay(stuff), k);
});
};
};
return search(searchSpace, function(val) {return val});
};
var arr=[1, 2,9,72,0,34,5,33,24,62,89,90,30,54,590,23,59,62,73];
solve(arr, function(a) {return (a.length==1 && a[0] == 5) ? a[0] : false;},
function (a) {return a.length < 2; },
function (a) {return a.slice(0, a.length / 2);},
function (a) {return a.slice(a.length / 2);}
);

Categories