March 2013 Archives

Asynchronous "Hello, world!"

For me, one of the toughest things about learning JavaScript is dealing with asynchronous code via callbacks.

Here’s a trivial “Hello, world!”:

var hello_world_string = '';
function storeHello() { hello_world_string += 'Hello, '; }
function storeWorld() { hello_world_string += 'world!'; }
storeHello();
storeWorld();
console.log(hello_world_string);

This obviously outputs “Hello, world!” to console.log. But this is completely deterministic, procedural code, and that’s not always the case in Javascript.

If you’re making an AJAX call from a client/browser to a server or pulling a value out of an IndexedDB database, you must process the results via a callback that fires after an unknowable period of time passes. To simulate this behavior, let’s change storeHello():

function storeHello() {
  setTimeout(function () {
    hello_world_string += 'Hello, ';
  }, 500);
}

This adds an artificial half-second delay before what we really want storeHello() to do happens. What now happens?

You might suspect console.log now spits out “world!Hello, ” but it actually spits out just “world!” Why? Because console.log() fires before the setTimeout() concludes and calls its callback. So the string is printed out without ‘Hello, ’. hello_world_string eventually gets set to “world!Hello, ” but only after it has already printed. Code execution doesn’t stop half a second when storeHello() is called and its setTimeout() sets a half-second delay. Code execution continues immediately with the next command, storeWorld(), and then the next, console.log().

If you really need the string components to print in the correct order after all functions have finished processing, you need to do additional work. One way to guarantee the correct order is by calling storeWorld() inside storeHello()’s callback function and calling console.log() inside storeWorld():

var hello_world_string = '';

function storeHello() {
  setTimeout(function () {
    hello_world_string += 'Hello, ';
    storeWorld();
  }, 500);
}

function storeWorld() {
  setTimeout(function () {
    hello_world_string += 'world!';
    console.log(hello_world_string);
  }, 500);
}

storeHello();

This correctly prints (after a 1-second delay) “Hello, world!” to the console.

You could also pass a callback into storeHello() that would get passed through to storeWorld() and then invoked after hello_world_string was complete:

var hello_world_string = '';

function storeHello(cb) {
  setTimeout(function () {
    hello_world_string += 'Hello, ';
    storeWorld(cb);
  }, 500);
}

function storeWorld(cb) {
  setTimeout(function () {
    hello_world_string += 'world!';
    cb();
  }, 500);
}

storeHello(function () {console.log(hello_world_string);});

Of course, you could name this anonymous callback:

var log_hello_to_console = function () { console.log(hello_world_string); };

and then invoke it as:

storeHello(log_hello_to_console);

Injecting the final step of the process as a callback gives you run-time flexibility to change what you do when the string is ready for prime time. You might instead want to pass in:

var log_hello_to_console = function () { console.log("*** " + hello_world_string + " ***"); };

or

var log_hello_to_console = function () { $('#greeting').html(hello_world_string); };

An alternative to placing callbacks inside callbacks would be to create an object responsible for gathering the string components, joining them in the proper order, and doing something with the full string (e.g., logging it to the console) after it received the final component. This approach would likely be several times faster because components can be gathered simultaneously (in parallel), rather than sequentially (in series) as happens when callbacks invoke callbacks.

Posted by James on Mar 22, 2013

JavaScript array iteration methods (Part I)

A quick review of The JavaScript Array API’s iteration methods:

Create a simple function:

var plusOne = function (val) { return val + 1; };

Obviously, plusOne(2); yields 3, plusOne(9); yields 10, etc.

Now let’s call plusOne() on each value in this array using Array#map:

var arr = [0,1,2,3,4];
var plusOneArr = arr.map(plusOne);

plusOneArr equals [1,2,3,4,5], as you can verify as follows:

JSON.stringify(plusOneArr) === JSON.stringify([1, 2, 3, 4, 5]);

Now, let’s look at Array#forEach:

var sum = 0;
var addToSum = function (val) { sum = sum + val; };
arr.forEach(addToSum);
console.log(sum);

The value of sum is now 10. But there’s a better way to calculate this, using Array#reduce:

var addToRunningCount = function (runningCount, newVal) { return runningCount + newVal; };
arr.reduce(addToRunningCount, 0);

This returns the value 10 in two lines, versus the previous four lines. Array#reduce takes a callback and a starting value (here 0). If we had wanted to multiply the numbers 1 through 5 together, we could have done the following:

var currentVal = function (prevVal, newVal) { return prevVal * (newVal + 1) };
arr.reduce(currentVal, 1);

This returns 120 (1*2*3*4*5). arr passes in 0, then 1, then 2, etc. up to 4. Each iteration, this becomes newVal. We add one to it, then multiply it by the return value of the last iteration. So it goes: 1, 2, 6, 24, 120.

Remember our old friend?

var plusOne = function (val) { return val + 1; };

Well, we could use this to compose the solution above, rather than hardcode newVal + 1:

var currentVal = function (prevVal, newVal) { return prevVal * plusOne(newVal) };
arr.reduce(currentVal, 1);

This gives the same result, 120. We could instead have used “partial application,” passing plusOne into a function that returns a function, like this:

var modifiableCurrentVal = function (modifier) {
  return function (prevVal, newVal) { return prevVal * modifier(newVal) };
};
var currentVal = modifiableCurrentVal(plusOne);
arr.reduce(currentVal, 1);

For a nice write-up on partial application in Javascript, see this Ben Alman post.

Posted by James on Mar 21, 2013

JavaScript array iteration methods (Part II)

Our next stop on our trek through Javascript array iteration methods (begun in Part I) is Array#filter. We’ll start by creating a function that takes a value and returns true or false, depending on whether the value is or is not greater than 2:

var greaterThan2 = function (val) { return val > 2; };

We can now filter any array to find all values > 2 by passing greaterThan2 as a callback to Array#filter:

var arr = [0,1,2,3,4];
var arr2 = arr.filter(greaterThan2);

arr2 is now [3,4]. arr is unchanged.

Like most of Javascript Array’s iteration methods, Array#filter passes the array element’s index position as the second argument when it invokes the callback. So you can filter not only on the element’s value but also on its position within the array. To see this, we’ll create a callback that returns true if and only if the element’s array index is < 3 (i.e., 0, 1 or 2):

var first3Elements = function (val, index) { return index < 3; };

Then we filter the array based on this callback:

var arr3 = arr.filter(first3Elements);
JSON.stringify(arr3) === JSON.stringify([0,1,2]) // true

Array#every returns true if and only if the callback function returns true for every value in the array:

arr.every(greaterThan2); // false (because 0, 1 and 2 aren't > 2)

But we can define another callback that will return true for every value in arr:

var lessThan5 = function (val) { return val < 5; };
arr.every(lessThan5);    // true

If you’re interested in whether one or more elements in an array satisfy the callback criteria, you can use Array#some:

arr.some(lessThan5);     // true
arr.some(greaterThan2);  // true

var lessThan0 = function (val) { return val < 0; };
arr.some(lessThan0);     // false

And that completes our tour of JavaScript array’s iteration methods. The one method I did not cover is Array#reduceRight. It’s basically Array#reduce, except that it processes the array starting at the end and working back to the beginning, rather than the other way around. This is pretty unimportant because you could always just call Array#reverse before calling Array#reduce.

Posted by James on Mar 22, 2013

JavaScript .bind()

Mozilla Developer Network provides a few nice examples of why and how to use .bind(). I’m going to add a few of my own here, but I encourage you to check theirs too.

Let’s say you have a john object with a function that knows how to get its own name:

var john = {
  name: 'John',
  getName: function() { return this.name; }
};

and a mary object that doesn’t:

var mary = {
  name: 'Mary'
};

You can call .getName() on the john object and get the name back:

john.getName(); // 'John'

But you can’t do that to the mary object:

mary.getName(); // TypeError: Object #<Object> has no method 'getName'

You also can’t just call the function because it’s a method of the john object, not a global function:

getName(); // ReferenceError: getName is not defined

Since john and mary are both people, it would make sense for .getName() to be defined on their common prototype, but let’s ignore that solution for now and focus on how to create a function that lets us reuse john.getName to return the name of the mary object.

The simplest way is probably with .call(), which calls the function (in this case, john.getName) with a context of whatever parameter is passed into .call(), in this case, mary:

john.getName.call(mary);  // returns "Mary"

Another way is with .bind(). We create an entirely new function by grabbing the function we want to use (john.getName) and then binding it to the object on which we want the function to be called (mary):

var getMaryName = john.getName.bind(mary);

Now, when we call/invoke the getMaryName function, it will call john.getName and set “this” (in “function() { return this.name; }”) to the mary object, so the correct value gets returned:

getMaryName(); // 'Mary'

This is an entirely new function, not a method of the mary object. So, mary still does not know how to return her own name:

mary.getName();     // TypeError: Object #<Object> has no method 'getName'
mary.getMaryName(); // TypeError: Object #<Object> has no method 'getMaryName'

The function belongs to the global scope and is disembodied from the john and mary objects. And we have cluttered up the global namespace with another variable name and consumed additional memory by creating a new function you may never use again. A better approach is probably to create the new function and immediately call it. Let’s delete the variable and function:

getMaryName = null;

And instead define and execute the new function in a single step:

(john.getName.bind(mary))();  // returns "Mary"

This is a roundabout way of doing what john.getName.call(mary) does. But there will be times when you actually do want to create a new function that is bound to a particular object.

A more verbose, but possibly useful, way to do this is by defining and immediately executing an anonymous function into which you pass the object you wish the function to bind to, in this case, mary:

(function (obj) { return john.getName.bind(obj)() })(mary);  // returns "Mary"

To capture the value, simply assign the value of the function definition-and-invocation to a variable:

var mary_name =  (john.getName.bind(mary))();  // returns "Mary"
console.log(mary_name);

To summarize: func.bind(obj); takes a function (func) and an object (obj) and returns a new function that, when called, calls func with “this” set to obj.

You can also use .bind() to insert additional arguments at the beginning of a method call’s arguments list. Let’s give John the ability to set and get an array of his favorite people in the world and make sure — because everyone loves their mother and would never want to forget their mom — the array always holds at least John’s mom. We’ll create a method that takes the arguments array, adds ‘mom’ at the beginning, and then stores the array in john.favorite_people:

john.set_favorite_people = (function() {
                              this.favorite_people = Array.prototype.slice.call(arguments);
                            }
                           ).bind(john, 'mom');

We’ve defined a method (john.set_favorite_people) that sets john.favorite_people with an array holding ‘mom’ plus all the arguments passed into the set_favorite_people method call.

Now John can stop worrying about forgetting his mom because she’s always automatically listed first in his list of favorite_people:

john.set_favorite_people();
john.favorite_people         // ["mom"]

john.set_favorite_people('dad');
john.favorite_people         // ["mom", "dad"]

Posted by James on Mar 24, 2013

JavaScript: Calling back from inside callbacks & recursion

Let’s say you have an array of arrays:

var a = [1, 2, 3];
var b = [4, 5, 6];
var c = [7, 8, 9];
var abc = [a, b, c];

You can define a callback:

var lessThan5 = function (val) { return val < 5; };

and then call it on any of the single-letter arrays:

a.every(lessThan5);  // true
c.every(lessThan5);  // false

But what if what you really want to do is test whether every atomic value in the three subarrays held by abc is less than 5? You could (incorrectly) try this:

abc.every(lessThan5);  // false, but not testing what you believe

To see that it’s not working as we want it to, let’s create this callback:

var greaterThan0 = function (val) { return val > 0; };

Since every value in every array held by abc is > 0, we want this callback to return true, but it still returns false:

abc.every(greaterThan0);  // false

abc.every is looping over an array of arrays, not an array of primitives (integers). What we really want is to have the callback called once for each array in abc call array.every(greaterThan0) on whatever array it receives. We need an intermediate callback, or a callback that calls .every() with another callback. How might we do this?

abc.every(function (array) { return array.every(greaterThan0); });  // true!

This works. We can prove this by adding a fourth array holding a negative value and watching the function return false:

d = [-1, 10, 11];
abc.push(d);
abc.every(function (array) { return array.every(greaterThan0); });  // false

But this is messy and gets even messier if you add another layer (or more) of callbacks. How can we clean this up?

Instead of using a function literal as our first callback, we can store the function in a named variable and pass in the variable:

var arrayGreaterThan0 = function (array) { return array.every(greaterThan0); };
abc.every(arrayGreaterThan0);

To summarize:

var greaterThan0 = function (val) { return val > 0; };   // inner callback
var arrayGreaterThan0 = function (array) {               // outer callback
  return array.every(greaterThan0);
};
abc.every(arrayGreaterThan0);                            // invocation on abc

What if we don’t know till runtime how many levels down into subarrays we must descend before we hit primitive values? Then the callback can’t know in advance whether it’s being handed an array of arrays or an array of primitives. But it can test what it has been handed and either call itself (if it has received an array of arrays) or call greaterThan0 (if handed an array of primitives):

var greaterThan0 = function (val) { return val > 0; };   // leaf-level callback
var arrayGreaterThan0 = function (array) {               // recursive outer callback
  if (Array.isArray(array[0])) {
    return array.every(arrayGreaterThan0);
  } else {
    return array.every(greaterThan0);
  }
};
abc.every(arrayGreaterThan0);  // false

If arrays are wrapped inside arrays inside other arrays, it will recursively descend down and down, however far it needs to, till it hits primitive values.

To make sure this works correctly for our array of arrays, let’s change a value and confirm the result changes:

abc[3][0] === -1;  // true
abc[3][0] = 43;
abc.every(arrayGreaterThan0);  // true

Now let’s test the recursion against an array of arrays of arrays:

var aaa = [[[1,2],[3,4]],[[5,6],[7,8]]];
aaa.every(arrayGreaterThan0);  // true

aaa[1][1][1] = -10;
aaa.every(arrayGreaterThan0);  // false

But what if the original array is simply an array of integers? It fails!

simple_array = [1, 2, 3];
simple_array.every(arrayGreaterThan0);  // "TypeError: Object 1 has no method 'every'"

We’ve assumed the original array is at least an array of arrays. If it’s a simple array, the callback fails. How can we correct this? Instead of assuming we received an array and testing what its child is, we can test what we’re actually handed and respond accordingly:

var greaterThan0 = function (val) { return val > 0; };   // leaf-level callback
var objGreaterThan0 = function objGreaterThan0(obj) {    // recursive outer callback
  if (Array.isArray(obj)) {                              //   not yet at leaf level
    return obj.every(objGreaterThan0);                   //     recurse
  } else {                                               //   at leaf level
    return greaterThan0(obj);                            //     call leaf-level callback
  }
};

simple_array = [1, 2, 3];
simple_array.every(objGreaterThan0);    // true

simple_array.push(-66);
simple_array.every(objGreaterThan0);    // false

And it still works with arrays inside arrays inside arrays:

var aaa = [[[1,2],[3,4]],[[5,6],[7,8]]];
aaa.every(objGreaterThan0);             // true

aaa[1][1][1] = -10;
aaa.every(objGreaterThan0);             // false

This is probably not the cleanest, most efficient solution, but it works. More to come.

Posted by James on Mar 22, 2013

Major improvements to JimmyJukebox

I’m pleased to announce JimmyJukebox (Ruby gem; Github code) now offers classical music as well as jazz. Other improvements include the ability to limit the number of songs downloaded, the ability to erase a song you don’t like, and the ability to replay the previous song.

Posted by James on Mar 01, 2013