What do you want to learn?
Leverged
jhuang@tampa.cgsinc.com
Skip to main content
Pluralsight uses cookies.Learn more about your privacy
JavaScript Design Patterns
by Aaron Powell
Useful design patterns for JavaScript development
Start CourseBookmarkAdd to Channel
Table of contents
Description
Transcript
Exercise files
Discussion
Learning Check
Recommended
Common Object Patterns
Introduction
Hi. Welcome to JavaScript Design Patterns. My name is Aaron Powell, and throughout this course we're going to be looking at some tips and techniques to make more maintainable JavaScript Web applications and non-Web applications. We're going to be looking at a number of different design patterns which can be useful in making you achieve these goals. First off, we've got to understand exactly why we want to have some design patterns. The primary reason is, like any other application that you're going to be viewing, using JavaScript requires you to have a certain level of discipline to make sure that you can maintain your applications through the long run of your project. Many of the patterns that we will be looking at you can find more information about on my blog or you can follow me on Twitter which I occasionally blog and tweet about technical information.
Function argument patterns
The first series of patterns that we're going to be looking at are some common patterns you've come across when working with JavaScript objects. These aren't specific patterns in their own but more useful patterns that you'll often be finding that you're doing already and just some tips about how to use them more efficiently. The first thing we want to look at is function arguments. We're going to start with a code example. In this we're creating a similar function that takes three arguments to it. Inside the function we do some operation against those arguments, we add each one together, and then we return the resulting value. If we look down below the function definition, you'll see that we're executing this function three times. The first time, we're passing in three arguments, 1, 2, and 3, and from this we'll be expecting a result of six. But in the second example, we're passing in four arguments instead of the three that's expected to the function. And in the final example, we're passing in only two instead of the three which is expected. So how would you be expecting JavaScript to be dealing with this? Unlike more traditional programing languages you might be familiar with, such as C-Sharp and VB, arguments in JavaScript are a bit more dynamic. They don't actually have to exist, which means that you don't have the same method overloading features that you do of some, say, .NET languages. Another thing about arguments that are in JavaScript is that they're untyped just like every other variable; meaning that you don't need to explicitly define the type of the argument or variable that you're creating, so you can pass in strings or numbers or any of the other types within the JavaScript type system into a function without it concerning about what the argument type is. So if we think back to our previous example, in the -- in the third of the code snippets that we were executing, we only pass in two of the three expected arguments. So what happens to the third argument? Well, JavaScript immediately will assign any argument that hasn't been provide to undefined. So we will still have A would have equaled 1 and B would have equaled 2, but C would have equaled undefined. So in that -- in that third code example, we would have had an output of NAN or not a number, as JavaScript is unsure of how to combine those three values. But if we think back to the second of the code examples where you passed in four arguments, because we were only expecting three, the fourth one is just omitted by JavaScript. It doesn't bring up a runtime error when executing, it just simply ignores the argument. Sometimes you might actually want to be accessing these arguments even if they're not specified. JavaScript provides a very easy way in which you can do this through an arguments object which exists with inside every function. The arguments object is a very special object in JavaScript. It is kind of like an array but it's not actually an array; meaning, you access all the arguments through a numerical index. So the first argument is accessed through the index of zero, B through the index of one, and so on. The arguments object also has a length property, so you can iterate through it as though it was an array, but because it's not actually an array object, you're unable to perform the actions such as sorting or filtering as you would with a normal array. So there's a few minute details that can trip you up if you're expecting the arguments object to act as an actual array. But this does mean we can do some interesting things such as we're doing in this code example. Here we're taking the same concept of the previous function where we want to add up all the arguments that are provided to us, but instead of passing them in as named arguments and accessing them through A, B, etc., we're just accessing the arguments object, going through it as though it was an array, summing up all those values, and then returning it. So it's a similar logic that we had in the previous example but not quite as detailed. This concept is also used quite commonly in a lot of JavaScript libraries that you're probably familiar with, one of those being jQuery. If you think about the default jQuery constructor where you could pass in a various different number of argument types -- you can pass in a string as a single selector; you can pass in a function to apply DOM radio _____; you can pass in a DOM object and turn that into a jQuery object; you can pass in a string and another object to perform a selector from that point onwards; or you can pass in a simple array of numbers or strings or any other values and jQuery will allow you to operate against those. Inside the JavaScript function for jQuery it will actually check against the types which have been passed in and make logical assumptions about what you're trying to do. If it's a string, it will first check to see if you're trying to execute a selector; and then if you're not, it will attempt to create DOM elements and so on and so forth. This allows you a lot of functionality against a single method body where in many other languages it would actually have to create multiple methods and do method overloading.
Chaining
The next design pattern I want to look at is the chaining design pattern. You're probably familiar with this if you're working with a lot of .NET APIs that have been producing in more recent years the concept of a fluent API, allowing you to execute something directly at the end of a previous method execution. This is popularized by LINQ in the .NET space. Or if you're familiar with jQuery, jQuery is a great example of a chained API for JavaScript. This code snippet down the bottom illustrates the kind of goals that we're trying to do with a chained API. First off, with jQuery we're providing a selector where we're looking for the elements of a class called "foo." The next thing we want to do is add to all those elements another class, then call the fadeIn method, and finally bodify the html. Essentially this is saying, execute these following three lines of code based off of the initial jQuery selector without having to assign that to a variable and then execute separate method invocations against that particular variable. In this example, I've got a simple little calculator which I've created. I start off by assigning the initial value for the calculator, which is going to be zero, and then perform some add and multiply methods against it. I finish up by calling equals which will then allow me to provide a call back function of something that I want to do. So let's have a look at how you would create a chained API. So here I have the skills from that calculator which I've created before, and then at the bottom I have the execution of that same code that we had within our slides. If I jump over to a command prompt so I can execute this with a command line JavaScript tool such as node js and execute it, you'll see that we get this error immediately -- type error, cannot call method add of undefined. If we look back at our code, it might not be obvious initially as to what that means, and we haven't -- haven't said that we want undefined. What has happened here is JavaScript, like languages such as Ruby, has an implicit return value of every function execution. If you don't specify a return value, such as I haven't yet, this will immediately return the value of undefined. This means that when we've called the second add method on line 17, it's expected that the previous add method has returned something that I can operate against. It actually hasn't, and this has then resulted in the error which we saw. If the add method had returned something, we could potentially have the same problem at multiply or equals as they themselves are not returning a particular value. So let's start off by implementing our chained API. To do this we first need to return a value from our add, multiply, and equals methods. And the value we want to return is the "this" value. So I've modified all my methods to return the value of this. In JavaScript the this keyword is a little bit special. It represents the current state which the method was invoked off of; meaning, that when it's chained API, the first time we call add, the this value will be the calculator. Because we're returning this, the next time we call the add method on line 17, it is still the instance of the calculator that was passed to the first add method, it's just been returned again. And we can continue on this way multiple times to produce our changed -- chained API. So if we go back to our command window and execute the code again, you'll see that we didn't have the error that we previously had, but we've also got no execution really have happened. We didn't get the equals method executing the code that we were expecting to execute. It's because we haven't enabled the method bodies. So let's go ahead and actually implement the method bodies as we require. I've started off here by implementing the add and multiply functionality. Through JavaScript closures, we're going to be capturing the start value, which was the initial value passed into our calculator, and we're just going to continue to modify that. So in the add method, we're going to add to it, and in the multiply, we're going to multiply it by the value that was passed in. For the equals, though, we need to work out how do we -- how do we handle the function that has been provided. All we want to do is we want to invoke the call back function because the function reference has been passed in, and pass in the start value. This does mean that when the equals function executes, we will get a single argument that has been passed in called "results." If we go back to our command window and execute this piece of code, you'll see that we get the value of 9 output which is what we have been expecting. So now that we have our chained API written, we might want to be taking into consideration the value of this inside of each of our functions. As I said, the this value is a little bit special and it can be modified. If we want to be careful with our chained API and ensure that no one is going to be doing something that we're not expecting with it, we can assign the value of this to something and capture it through JavaScript closures. A common way of doing this in JavaScript is to assign the value -- a variable named "that" to the value of this. So withinside our functions instead of returning this, we'll return that. You can obviously name this variable to something that is more obvious and easier to understand within the script of your application. If we go back to our command window and execute your code, you'll see that we've had no change because the value of that represents exactly what we wanted and what we were expecting. So to recap: The concept of the chained API is something that is very common in a lot of programming languages particularly .NET. .NET exposes this through the LINQ API and it's probably what you're most familiar with this chained design pattern from. In JavaScript you'll be familiar with it if you'd worked with jQuery as it uses it quite extensively, and one of the primary aims of it, in JavaScript in particular, is to reduce character size. Because JavaScript has to be submitted over the wire we want to minimize the amount of data that we're providing. If we don't have to assign our objects to variables, we can more optimize the bytes that are being sent down and the chain design pattern can help you with this. The idea behind the chain design pattern is to return the value of this, or at least an object that represents the next point in your API call, allowing the user to execute continuous functions based off of that. As you also saw, we can assign the value of this to something if we're not able to trust the caller which is going to be executing our chained API. And as I mentioned, you can -- you don't have to return the this value, you only have to return something that makes sense for the next continuation of your API chain.
Observable Properties
The next design pattern that I want to look at is the observable properties design pattern. In JavaScript we don't have method bodies like we do in, say, .NET. We only really have simple value types so how can we react to those? If we're building a rich client application in .NET, say, with _____ or WPF, we could be implementing the iNotify property changing and property changed interfaces allowing us to apply a bit handelers and react when a property has had a value updated or even canceled a property before its update has happened. And we can do this because .NET properties allow us to have method bodies. In JavaScript our properties are more closely related to public fields in .NET, so how can we address the fact that we don't have the ability to create a method body but still provide the functionality that we would be wanting? The most common way to do this is through a pattern known as methods-as-properties, and this is something that is quite common in a lot of JavaScript libraries these days such as Knockout.js. Essentially what it does, instead of using a public field to create our property values that we read and write from, we create methods and we use those methods to update and retrieve the values. So let's have a look at how we can use the methods-as-properties to create an observable property design pattern.
Creating Observable Properties
So here I've got a very simple little book API which allows me to create new books and provide a name and a price. These are both exposed as public values that we can access through a name and through a price. We also want to be able to react to when the price is changing or when the price has changed and perform operations based on what we're doing there. If we look down the bottom of this code, you'll see how we want to execute this. First off, we're going to be creating a new book, providing it with a title and a price. Next, we want to access the name of that book. But because this is now going to be a method so that we can observe a change against it, you'll see that we're passing -- we're accessing it through a method invocation. The same thing goes for price. On line 25 we're creating a method that allows us to react to the price changing. In this case, if the price is going above a certain value, we want to cancel it because it's possibly an error in our system. Someone might have modified our JavaScript and checked it in that we didn't catch it and it's made it through our testing, or this can even be used to react to our testing system. At the moment I'm just going to be doing something simple such as looking at it an error, but returning false from this method should cancel any change from happening. When the price has changed, I just want to console log out a bit of information to say that the price has changed. This could be acting as some debugging information. And I'm finishing up by modifying the price a couple of times just so we can see this API in action. Now, if we go over to a command window and execute this, again, we will just use node js because there is no user interface that we need to be concerned about. You'll see that we've got undefined for both our name and price and none of our event handlers have been executed. If you remember from the previous section on the chain pattern where I mentioned that functions implicitly return a value in JavaScript, we're not returning a value yet so they're going to be returning undefined. So what I'm going to return is the name property that is captured through the initial book creation method, same with price. Now, if we go back to our console window and execute that, you'll see that we've successfully output the value that was provided through the initial creation of the book for both the name and the price, but we still haven't executed our event handlers, so we haven't been able to change our price nor have we been able to react to that price change. So the first thing that we're going to need to do is capture these callback handlers that are being provided to us. What I'm going to do here is create two arrays which we're going to be pushing callbacks into. So I've created two arrays at the top of my JavaScript closure scope; inside the on price changing method I'm just going to add the callback into the array of events that have been provided. I'm going to do a similar thing in the on price change but push it into, obviously, a different array. Now, if we go back and execute the code, still we had no change because we're still not capturing and reacting to the price change methods as we're expecting. If we come into our price property that we've got here, you'll see that I'm passing in a value which will represent the new value that has been provided. The first thing I want to do is check to -- to see that a value was actually provided to us. If you remember from our first section of this module where I talked about function argument patterns, you'll know that if a function is invoked that a value has not been provided to, it will be assigning that argument to undefined. So first off, we obviously want to make sure that they're not providing an undefined value for the price because that would be invalid. The next thing we want to do is make sure that the price is actually different that has been provided to the existing price because there's no point updating if we don't need to. So assuming that both of those checks pass, we can change our price to being the value. We're still going to return the price because this can allow for an example of our method chaining as we had previously. So I can both update and retrieve the value at the exactly the same time. But we're still not dealing with the callbacks that have been provided to us. The first thing we want to do is go through the price changing callbacks reacting to any attempt to cancel the price changing event. So what I've done here is I've gone and created an array that will go through price changing callbacks that have been provided, the event handlers if you were, executing each one in sequence providing the book as the first argument and the new value that we're updating to and checking the return type. If the return type is not true, they've returned false, then we want to just abort -- we want to return the current price because we want to continue our chainability of this API, but we don't want to be allowing the rest of the operation to continue, we don't want to be updating the price at all. If that all goes successfully, we want to update the price and then finish off by executing all the price changed handlers that have been provided to us. Once the value has been updated, we'll be iterating through the price changed event handlers, executing each one as we go, providing in the current book as the first argument. So if we execute this again, in our command window you'll see that we've got the first two lines that we've previously had, the name, and the book price, and you'll see that the book price has changed to 19.99, and then we finish off with the unexpected error. If we go down to bottom of our API and look at our execution, you'll see that the first thing we did was attempt to update the price. This will have attempted to go through the price changing handler, the price won't have met the file condition and successfully returned, allowing us to continue on, and finishing off with the price changed handler that we passed in which is output that the book price has been updated. Finally, we try and update the value to 200, which then produces an error and then aborts, and you'll notice that we didn't execute this second price changed handler more than once. If I was to change this down to 20 and re-execute the code, you'll see that we get the price changed handler has happened twice.
Observable Property Futures
Something that is worth pointing out on this idea of methods-as-properties pattern is that there's a change coming as part of ECMAScript 5 or that has already come as part of ECMAScript that does allow us to provide method bodies for our properties. But something that needs to be of note is that this is only available in current generation browsers. By this I mean, IE9 plus as well as the current generation Firefox, Chrome, etc. This does mean that we can do .NET-like properties and provide the same kind of functionality that we've got withinside of the previous code example that we've looked at. So here's a look of how we would define a function property in ECMASscript 5 that has a method body. First off, we need to use the Object.defineProperty method to do our property definitions. The first argument that we need to provide to this method is the object that we want to add the property to, in this case it would be our book object or our "this" object; we then need to provide the name of the object -- sorry, the name of the property that we want to create; and then the get and the set of the bodies that we want to execute. You can also define multiple properties through the define properties method if you want to create your larger API in a single hit rather than doing multiple executions like this. For the define properties method you just need to expand out your JSON object that you're passing into the method to have each of the method properties on there. The ECMAScript 5 properties are a little bit more powerful than what we can achieve today with the observable properties pattern, as in, we can also define things such as properties that cannot be updated, properties that cannot be removed, and properties that cannot be iterated across if we're using things like the foreign loop in JavaScript. But as I mentioned, this is only available in the current generation browsers, so unless that is your only target market, this is something that you can be -- be using very carefully in the projects that you're working on. So just to recap this section of the module that we've looked at: We wanted to look at how we can implement something similar to the idea of the iNotify property change and changing events withinside the .NET framework to react to when property values are changed. We've done this by implementing the observable property pattern and using method bodies as our properties instead of using public fields. What we've also seen is that the way we implement this is by checking the incoming value that has been passed through our function. In our example, we checked to make sure that the value was provide, that it wasn't an undefined value, and that it is actually something that we want to update. You could also put in some validation logic. If this was much more a service centric application, you could provide validation to make sure that you're meeting minimum length of a string or that REGEX is passing the value, and then provide error states happening against that. Ultimately, what we aimed to do here is return some kind of a private variable that has been stored that is capturing the state of the property. So this case, we were just using the initial value that was provided through the closure in JavaScript, but you could be storing this into a private variable withinside the closure scope. Lastly, we exposed a couple of public methods that allowed us to provide functionality into our methods in the form of event handlers, and then executed those through a loop, checking to see the initial runs, the changing events were not actually attempting to cancel the operation, and if they were, then we would abort the update process.
Timer Patterns
Introduction
In this module, we're going to be looking at some JavaScript timer patterns. First off, I want to just do a bit of introduction to JavaScript timers. In JavaScript, there are 2 different kinds of timers that you could be working with. One is called setTimeout; the other is called setInterval. Both of these timers take 2 arguments. The first being the function that you wish to invoke. The second a period of delay for when this function is to be executed. There are other overloads to both of these methods, the delay passing a string is the first argument. And the delay period is the second argument. But it's recommended that you do not use this for the same reasons you would not use the eval function. Some browsers also implement a way to pass in arguments to the function that is being invoked through the setTimeout or the setInterval. But this is not consistently implemented across all browsers so it's recommended that you avoid that as well. The setTimeout function will execute the function that you provided once after the delay period has expired. Whereas the setInterval will execute the function continuously with a delay period specified between each execution. There's something worth noting though about the delay period that could be provided. If you specify a delay period of less than 4 milliseconds, JavaScript engines will actually bump this to 4 milliseconds as it's the smallest time period that they will actually allow for a timeout to be delayed. This means that if you specify a timeout period of 0 milliseconds, it will immediately be bumped to 4 milliseconds so it has no benefit over putting something to 1, 2, 3, or 4 milliseconds. They will all be treated as the same and their priority order won't change. Another thing that's important to remember about timers is that a timer cannot execute until the outermost function which it was created within has completed its execution path. This means that even if you were to create a timer with a small timeout period of say 4 milliseconds which will essentially tell the function to execute immediately, it cannot do so until the function which created it, be that a DOM ready event or any other function that could be executing, it will not run the function you've specified until that function itself has completed.
Timer overview
So let's have a bit of a visualization of what a function stack would look like using timers. So here I've created a simple function that just wraps a couple of setTimeout invocations. Here I'm passing in 3 anonymous functions and I'm all setting them to a 0 timeout which implies that I just want to execute that when they're next available to be executed. And then executing this wrapper function that's been created. So what will happen is that these 3 anonymous functions we put into the JavaScript timer stack, they will sit there and await the completion of the fn function's execution, and then the timer stack will be able to start processing. This can actually be interrupted though as we'll see in the next little example. So if we want to visualize timers in a slightly different way, this is a bit more of a graphic visualization of what the timer stack would look like. Here's our 3 functions that we've provided and each is just sitting there waiting for execution. As soon as the timer stack has been released, the first function will be popped off the top and begin its execution. But say we had some other long-running processes or other asynchronous processes happening, say we had an AJAX Request happening in the background, it's possible that this AJAX request could finish before the next function gets executed in the timer stack. This AJAX Response, its handle, would then be popped to the top because it's the next immediate thing to get executed. It's been waiting the longest. So it would be popped on the top of the timer stack and executed at the next available point. So the AJAX Response could be processed by our code and its handle executes and our timer stack sits down with those 2 functions that we provided. Eventually the thread will be released and the timer stack can move up and put the next function as the next piece of JavaScript to execute and the process begins again.
Asynchronous Execution Pattern
So the first pattern that I want to talk about is the Asynchronous Execution Pattern. With browsers, they are typically, the UI component at least, single threaded. This means that the browser can only be doing either updates to the UI so modifying the DOM or executing JavaScript at any given time. It's incapable of doing both simultaneously. To do that, that's something where wordworkers would be coming into play. But that is beyond the scope of this module. Since the browser's UI stack is single threaded and can only be executing one logical concept at any given time, long-running JavaScript can cause the UI to become unresponsive or at least appear that way to the user. This was very common in auto browsers as they had a much lower threshold for UI blocking and if you're doing a lot of, say, complex DOM manipulation in JavaScript, it would appear that the browser was unresponsive and ends up being a very poor user experience as the user thinks that their application might have crashed. So the idea of the asynchronous execution pattern is to split out long-running JavaScript blocks using setTimeouts. So say we're processing an array that might have hundreds of items in it, this could take a long time to process. So I want to ensure that we release back to the UI thread periodically so it can do any updates and provide any feedback to the user that is required so they don't think the application has frozen. Something that is also very important about this is that while we split up the long-running process using setTimeout blocks, we ensure that there is enough of a gap between each of the timeouts that we're specifying to allow the UI thread to start responding and not immediately jump in to the next JavaScript block.
Demo: Asynchronous Execution Pattern
So we want to have a look at a demo of how we can implement the asynchronous execution pattern. Here I've got a simple piece of JavaScript in a fnc project that is going to be calling off to a route in my controller and pulling down some data. This data is then going to be processed through an interray loop and we're going to be building up some DOM elements based off of the results. Eventually we're going to be appending this new DOM structure into an element that I've got on my page. From this eShop point of view, I'm just doing something very simple. I'm generating a renewable of a thousand items in length and then just allowing that to be returned to the browser. So this is a very trivial example but it's a very common scenario that we'll see in web applications, say if we're building a search results set, we could be doing that through AJAX. So if we come over to our browser and execute our code, you'll see that it doesn't appear to be doing anything too complex. We're outputting our list of numbers as we would be expecting. The problem that can arise though is we may not know the length of this ray or how long it's going to take it to process it. And on low-powered devices, such as mobile phones or tablets, processing this array could take a lot longer than we would like for the UI and not allow the UI to start responding. So one way we can get around this is to create a function that will allow us to defer the execution over multiple periods of a timeout. So I'm going to start by creating a function we would then use to execute our delay. So here's the skeleton of the function that I'm going to be creating that will delay our execution. I've named this function buffer as you can see up here on line 10 and it's going to take in 3 arguments. The first argument will be the array through we want to iterate through. The second is the function that we want to execute on every iteration, and the third will be a callback function to execute once we've processed the entire array. If I come down to my Get Response, I want to re-factor this code so that it's going to be using my new buffer method. So here's my re-factored Get Response handler that will be now using my buffer method. As you'll see the first argument that I've passed in is the results that we're getting back from our AJAX call. The second argument will be a function that is executing the same piece of code that we were doing within our for loop as this function callback is going to be acting as our for loop body. And finally I've created a function as the third argument that will be doing the appending to the DOM. So now we need to go up to our buffer method and actually implement the processing of the array. So here I've defined the for loop that will be processing our array. The first part of the "for" loop I've created a variable called start which will represent the date/time that this process has started at. I've done this by using the plus operator against the new date constructor which will actually return the number of milliseconds that have passed for our date rather than providing us with a date object ourself that we later have to process. For the condition to determine whether this array needs to continue, the first thing I'm doing is making sure that the current position of the array is still less than the total number of items in the array, that our result value doesn't equal false, and the current date minus the start date value is still less than 50. This means that we're going to put in a buffer of 50 milliseconds for each processing of the array. This means that this "for" loop will run for a maximum of 50 milliseconds but will also be able to break early if we've reached the end of the array or we tell that we want to explicitly abort from with inside our item callback. Finally I'm just incrementing the value of "i" so that we can keep track of the position within the array. For the body of our for loop what we're going to be doing is invoking the second argument that was passed into our buffer function. And passing in, so this context being, the current position, the current item in the array and we'll also pass in the current item and the position in the array as the 2 arguments that this function has. We'll then also capture the return value of the function which if you'll remember from our previous module, a JavaScript function will implicitly return a value of undefined if you don't specify anything meaning we can abort early from our for loop by returning false. Or if we don't return anything we will just ignore this and continue on. So assuming our for loop has completed it may have completed because our time period has expired. So if the time period has expired, we want it to restart from the current position in the array and continue processing the same function over a period of time. To do this, I'm going to add a couple of conditional checks. First off, we want to make sure the current position of the array is less than the total length of the array and the results of the last callback was not false. So inside the truth eval of this conditional we want to use a setTimeout again to reinvoke the same function that we've just executed and then put in another buffer of 20 milliseconds. I'm going to use the arguments.callee property because that will give us a pointer back to this function that is processing our loop rather than having to declare as a local variable. Alternatively if we have returned false or if we have reached the end of our array, we want to call the callback function that we passed in as the third argument. I'm also going to pass back the items. So if you go back to the browser and re-execute, you'll see that it operates exactly the same. We've got the same number of values have been outputted in exactly the same order. So what we've done hasn't provided us a large impact within our current scenario. But what it has done is provided us a way that we can deal with more complex and time consuming loops in a way that is not going to be detrimental to the browser, refreshing the UI, and ensuring that users are not under the impression that an error has happened and caused their application to crash. As I said, this pattern is most commonly used when working with low-powered devices such as mobile phones and tablets.
Recap
So just to recap. We've seen how we can use a setTimeout to process a large array or a time-consuming function and break that down over multiple executions split up over a time period. The reason we wanted to do this was that we can allow the UI of the browser some control back to process any pending UI changes and not appear to be unresponsive. We want to make sure that the buffer we're building in between our executions of the timeout methods is not too small that the UI is unable to process it but it's also not too long that our function is actually going to take an exceptionally long period of time to finally execute. As I said this pattern is most commonly used with low-powered devices or browser JavaScript engines that are not capable of executing code as fast as some modern browsers.
Recursive setTimeout Pattern
The next Timeout pattern I want to look at is the Recursive setTimeout Pattern. The recursive setTimeout pattern is most commonly used when you want to execute a piece of code over a continuous period of time. It's most commonly used when you want to query a data source and you maybe familiar with it if you've been working with AJAX long polling. This though may sound like what setInterval does. SetInterval being a way that you can specify a timeout period that you want to execute a piece of functionality over the course of. But there's actually a bit of a problem with using setInterval. Because JavaScript is asynchronous the setInterval method will not actually wait for the previous function to finish its execution before it begins the next timeout period. Ideally what we would be wanting to do is wait until the function that has been executed for, in full period, has completed before we can continue on. Let's say we're performing an AJAX request. We don't know how long this request may take. It could take a period of time longer than we've set with our interval so what happens if the AJAX response takes longer than our allowed interval period? Well, what will happen is the next interval will start up and start executing which means that we could be having 2 AJAX requests being processed at the same time depending on whether we have too short of an interval period, we could continuously execute AJAX requests and end up with them becoming out of order. So here's an example of how we could implement what I'm talking about using setInterval. You'll see here that we're using setInterval over 1 second and every 1 second we want to hit a particular URL in our application and then do something with the results. If the function or the AJAX request takes longer than 1 second to process, this setInterval will have multiples executing at the same time. And as I said, it is possible that these could become out of order because one response from the server might take a lot longer than the second response. And all of a sudden, the second response is being processed before the first one has returned back to the browser. So the idea of using setTimeout is that rather than using setInterval to say every X period of time we want to execute a piece of functionality, we use setTimeout and inside the response handle from our AJAX call we re-issue another request to setTimeout. This means that only one will ever be happening at any given time and it's not until the handle from our AJAX response is complete that we start up the next one.
Demo: Recursive setTimeout Pattern
So let's have a look at how we could go about implementing this. So here I've got a simple piece of JavaScript that will be calling off to an AJAX service that we have in our application and it is just going to be outputting some information about what is happening. If we have a look at our AJAX service though, you'll see that this is being processed asynchronously. And I've put in some logic to attempt to simulate a delay within our application. We're going to be executing a sleep of a random number of seconds between 5 and 20 just to simulate some latency that could be happening within our application. Eventually our handler is going to complete and it's going to return back a bit of information just essentially telling us how long it took to execute this function. If I come to my browser and load up this application. And using my developer tools, I'll come down to our Network tab. I'll stop capturing and network information. And you'll see that I've now just made a request to the slash home slash date route. You'll see that I've also made a second request to the home/date route and a third. But you'll notice that all of these are still listed as pending. So each of these is executing concurrently but none of them have actually responded. And you'll see that within our UI, we've started getting them back in an inconsistent order. We've got our first 3 back, 0, 1, and 2, in the order that we expect but the 4th one within our list was actually the 5th request to happen. The 5th request that has come back to us was actually request number 3. And you'll see this pattern being continuously taking on within our output here. And if we look down into our browser network tab, you'll see that each of them is taking a random period of time to execute. As I said this was just to simulate server load and server latency of our AJAX responses but because they're happening at different time periods, it's inconsistent as to when we're going to be getting the response back to handle. We're actually getting them in a different order from that which we would be expecting. So now let's see about re-factoring our method to using setTimeout instead of setInterval and avoiding the problem of the inconsistent ordering. The first thing I want to do is to change the setInterval call to setTimeout. The second thing I want to do is actually give a name to this function that we're executing within our timeout. This will allow us to have a point of back to it so that we can re-execute it easily. I'm going to call this getDate. Lastly with inside our response handler, the Get Call, I'm going to do another call to setTimeout. The first argument that I'm passing in to this setTimeout is appointed to our getDate function and secondly is the delay period. You could obviously make it a constant that represents this timeout period so we don't have to execute it multiple times. But in our simple little demo here, I think it's fine to keep that within the 2 separate locations. So I save this and then return back to our browser, I'll reload the page and we'll see what happens within the network tab this time. So I've just reloaded the page and I've got my network tab running again. You'll see that we've made a request off to the slash home slash date route and we're waiting for the response to come back from our server. You'll notice though that we've got no other responses started at this point in time. Although 5 seconds has most likely passed before this, we haven't started up a new method. You'll see that we got a response back. It took 80 milliseconds and it -- now that that response has returned to us, we started up a second call to our server. Although this is obviously taking a lot longer than it was in our previous example, we're not getting multiple requests happening simultaneously. And as you'll see, we're only ever having one happening because we're waiting until the response of the previous one has completed before we start the next attempt to request our service. So this is a lot more efficient as it reduces our server load by not having concurrent requests happening that ultimately we need to ignore one or the other of. So to recap, we've seen how we can overcome a potential problem with requesting our AJAX service over a continuous period of time in a way that uses setTimeout rather than setInterval to ensure that we only have one executing at any given time. The reason we want to do this is that setInterval is a little bit unpredictable across browsers. In IE, it will execute it in the order which the intervals are put into the stack and then it will process them as they come in regardless of whether there are other intervals that have been in the stack longer. But some of the other browser engines actually don't do this which is incorrect according to the JavaScript timer specification. The timer specifications state that it should be executing the intervals as soon as the time period has been processed regardless of whether the function itself has completed its execution. What we've done is broken down our call to our AJAX service using setTimeout. We only start the execution of the next one when we are ready to.
Asynchronous Module Definitions
Introduction
In this module we're going to be looking at the asynchronous module definition pattern or AMDs. Unlike languages such as C sharp JavaScript has no way that you can explicitly state that you have a dependency on some kind of external reference. There's no such thing as a using statement as you would be familiar with if you're coming from a dot net background. So this can raise a couple of interesting questions when we're trying to produce large complex JavaScript applications. How would we specify that applets of code relies on some other piece of code that's within our application? Say I've got a jQuery plug in and I want to make sure that jQuery is always available. The most current way is that we'll put in some conditional checks to make sure that jQuery is loaded and if it's not proceed to raise an error. We have no way to say if jQuery is not already available, bring it in. Also how do we prevent things such as scope leakage? In JavaScript it's very easy to accidently declare global variables. If you're familiar with the way that JavaScript scope works everything is functioned scoped rather then block scoped as you're familiar with from C sharp and vb.net. This means that if you don't declare your variables with inside a function they will be immediately added to the global variable which in a browser is the window object. This means that you can, you know, readily create global JavaScript objects very easily. Also the JavaScript operations in a browser are a blocking process. As you remember from the last module on tile patterns where I explained how JavaScript can cause the UI thread to be locked, this is also the same thing that can happen initial loading of a page occurs. Only a single JavaScript file can be processed at any given time meaning that you can have delays or you're including everything into your page. So if we can only be downloading and processing a file once at any given point in time how do we make sure that we've got dependencies on other files and that they're already included? And then what about Node.js? If you're not familiar with Node.js it's a server implementation of JavaScript using the V8 JavaScript engine from Google and it allows you to execute JavaScript as a server language like you would C sharp or VB or any other of those languages. So it doesn't have the same kind of restrictions that you would expect when using a browser. So how does it deal with the concept of including an external reference to a file since it doesn't have to download these? CommonJS is an attempt to standardize a number of common JavaScript patterns and practices. Many of the different patterns that have been submitted for CommonJS have various proposals to them about how they should be included either at a common understanding across multiple frameworks or at a language level. And the attempt is to make sure that JavaScript that is developed in all run time environments, be that for the browser or for the server or any other environment, they will all have a very similar development process to them. Currently there is a proposal of how we would do modules or including components that are not native to the current file that we're operating within. The current implementation that has been proposed for CommonJS is version 1.1.1 and it's very similar to the way that Node.js would do a module system.
Nodes.js Modules
So now we've got a bit of an understanding about what problem we're trying to solve here that we need to be able to include some external dependency into a JavaScript file. Let's have a look at first how Node.js would implement this. Here we've got the calculator object that we created in the very first module on object patterns and we want to be able to use this within our Node.js application. We want to make sure that it can be exposed and it can then be consumed Here's the code that we want to run from with inside our Node.js application. It's the exact same code that you would be familiar with from the first module and it's essentially creating a new version of our calculator and then performing some operations against this. So we need to think about how we're going to be able to include the contents of calc.js with inside this app.js file. And how do we make the calc variable available for usage? In Node.js they have the concept of a requires function and this allows us to specify a dependency that what we want to include. What I've done here is defined that I want to create a variable called calc and I want it to be including the calc.js file. To do this I used the requires function in Node.js. To that I have passed in a relative path to the calc.js file. In my application the calc.js is the folder level as the app.js file but if it was in another folder underneath the directory that our app.js is residing in we would include that folder name as well. Now we come to our console window and we execute app.js. You'll see that we've received an error. What it's saying is that the object calc is not actually a function and cannot be used as a constructor in the way that we're attempting to use this. If we come back to our application and go over to our calc.js file you'll see that we are actually declaring this so the question is why wouldn't this be exposed when we're using the require method? I'm essentially declaring this as a global variable with inside this file so it should be made available as you would be expecting within a browser. The difference with Node.js and the way it is implemented a module system is that it will implicitly provide you with a closure scope. So the way this file is actually executed is with inside of a function itself. So the contents of my file will be copied into a function that is created by the Node.js run time and then executed meaning that this calc variable that I'm defining on line one is never exposed publically. To make this available publically we need to explicitly tell Node.js that we want to export it. What we want to do is use the module object which is provided globally with inside our Node.js application. And then assign what we want to export to the exports property say as you'll see here on line 23 I'm using module.exports and then assigning that to the value of calc which we're defining on line one. Now if we go back to our console and re-execute the code you'll see that we get the expected output, the value of nine which according to the logic of our calculator is the correct value to be outputting. But if we take a look on line three, I'm having to use the new keyword here. But what if we didn't want to expose our calculator in a way that you had to create a new instance of it every time? What if we just wanted a bit more of a fluent API so that we didn't have to treat this as a constructor? If we come back to our calc.js file rather then assigning the calc variable to the exports, I can create an anonymous JavaScript object. Inside my anonymous object I can choose to expose any kind of function that I would like to expose for my API. Let's start by exposing an add method. With my add method I want you to be able to pass in up to two values, an x and a y value that's going to be added to our calculator that you can then operate against. Inside this function I'm just going to return a new instance of our calc, pass in x as the first value and then for the second value y or if you don't pass in a value, zero. This means that you could use the add method to create a new calculator instance. I can do a similar thing with multiplies and now we've created an API that we can interact with inside of our Node.js application. So if I go back to my app.js file I can remove the new keyword from here and then I can remove the initial constructive value. So now I can have this operate as if it were a fluent API. I could then reflect my API so I pass in one and two as the first two arguments, I can still perform the multiply function and then finally I can perform the equals function. If I come back to my console and re-execute our Node.js application you see that we haven't changed anything in the operation, we're still getting the same output value as we were expecting. So just as recap what we've done is inside of our Node.js application on line one the first thing we have done is say that we want require a specific JavaScript file. We've specified the path to the specific file that we want to include and assigned that into a variable that we can use with inside of our scope. Inside the API that we're exposing our calc.js file we're using the global module object and assigning the exports property of that to the API that we want to expose at for public consumption. By doing this we've managed to entirely encapsulate the initial calc function with inside of the closure scope and there is no way to access this from outside of this calc.js file.
Browser-based modules
So now that we've seen how we can use modules with inside Node.js we need a step back and consider how we can use this within a browser. Because the requires function is not part of the JavaScript language, it's part of the Node.js run time, same with the module object, we don't have that capability with inside the browser. Also because Node.js doesn't have to deal with http requests to download it's JavaScript files to operate against, we don't have the same issues inside Node as we would in a browser about including multiple files and how do we wait for them to be downloaded and processed and then made available to us. To address these problems there is a project called RequireJS. Essentially RequireJS is designed to pick up the limitations between the CommonJS and the Node.js module definition and make a module framework that is usable from with inside a browser. As I said it doesn't actually implement the CommonJS module pattern, there is more information on the RequireJS Website as to exactly why they are implementing it. But essentially it comes down to the fact that using Require and then just passing in a string to specify the path to the module that you wish to require doesn't work in browsers as it doesn't take into account the fact that we need to download the file and have the browser interpret it before it can be made available to us. So the API is provided for RequireJS is much more browser friendly and deals with the way JavaScript programmers in the browser are familiar and through call backs. But the RequireJS API is also available for Node.js, it's not specifically tied to the browser so you can produce modules that are usable both in Node and within the browser using a RequireJS as the module loading system. RequireJS is actually a little bit more then just a way to specify dependent JavaScript files. It's also useful for laying out your JavaScript applications in a structured manner. And it can be useful if you want to include other references such as CSS and html. RequireJS can also include those itself. But there is something that is worth noting as a cautionary tale with regards to RequireJS. Because of the way browsers operate, if you want to use a combination and minification of your JavaScript essentially taking all your JavaScript files and combining them into a single JavaScript file which is a good idea for performance, it can actually have a detrimental effect on RequireJS because it expects the file structure to be maintained. This is something that you need to take into consideration when you're looking to use RequireJS as a module loading system within your application.
Demo: Creating AMD with RequireJS
So let's have a look at how you would go about using asynchronous module definitions with RequireJS and inside of our browser. Here I've got a very simple application where I want to load the public timeline for a particular Twitter account. This is a fairly basic scenario but it allows us to look at how we can use a couple of different aspects of RequireJS. The first thing that we want to do is include a reference to the RequireJS library. You can download this through NuGet, if you're working with Visual Studio project or you can get it from the RequireJS Website. Once you have included this in your project you'll have a number of new script files available. The primary one of interest is Require.js. There is also a minified version so you can use it on your production systems. The first thing I want to do is go to my layout.cs html file and add a reference to require JS. So now that I've added a reference to it I need to make sure that RequireJS knows what to do or where to find my first module. There is a convention within RequireJS that allows you to do this by using a data attribute on your script tag. To do this I use the data dash main attribute on my script tag for RequireJS and specify the location of the first JavaScript file that I want to be executed. This will essentially be the root of my JavaScript application. Notice that I haven't include the dot js extension on my slash scripts slash main path. This is because RequireJS will assume that if you don't specify an extension it is going to be a JavaScript file that you want to load so it's going to have a dot JS extension on that. Depending on whether or not you use a dot js extension there is some differences to the way RequireJS works. If you include a dot js extension it will assume that you've provided it an absolute path to the file you wish to load. Whereas if you don't include that it can use an implied path based off of where the main JavaScript file that you have loaded exists. So the next thing I need to do is add my main dot js file. It's on my scripts folder I've created my main dot js file. And I need to tell RequireJS that I want to do some operations here. The first thing I'm going to do is tell it that I've got some dependencies that are a require because the way I want my application to work is I'm going to be looking at the text box to work out what you have entered as the Twitter user name you wish to search for and then attach some event handles. Here I'm using the requires function to tell RequireJS that this is an application that I will be wanting to execute through its API. The first argument to the require function is an array of dependencies that I want to be loaded for my function that's going to be executed. In this case I want jquery as a dependency of my application so the first argument that I'm passing is jquery. RequireJS has some intelligence around the way it will load popular script libraries such as jquery. If we come to our layout.cs html file, you see that on line seven the line directly before RequireJS I'm including jquery. Because jquery is not actually written as a RequireJS module RequireJS has some smarts to know that just you providing the jquery keyword it will attempt to locate that within the loaded JavaScript files already and include that with inside our function. The second argument of our require method is a call back function to execute once these dependencies have been loaded. The arguments that are passed to the function is the dependencies in the order that they are specified within the first argument of the require method. In this case I'm specifying I'm going to be assigned jquery into the DOS object so it's a common looking API. Because this main js file maybe executed before the document's ready, I still want to do all my operations with inside a jquery document ready function. So I could perform exact the same operations as I would be using with jquery if this wasn't using RequireJS. So I can do a document.ready method. Inside this I want to then attach to the form that is on our page and then provide a listener to the submit event. So here I've set up a handler for my forms submit event and I want to just cancel the default operation because I'm actually not going to be submitting any data. I'm going to be handling all of this through AJAX. Now I can go ahead and perform all the other operations that I would be wanting to do such as looking up for the user name that has been submitted. But how are we actually going to load all the tweets from the Twitter API? Well because this functionality here is really specific to reading from the form and then ultimately displaying back into the DOM I want to have a separate API that is responsible for interacting with Twitter. To do this I've got to create a new folder with inside our scripts folder and create a new JavaScript file called API. So now that I've created my new API that's going to be responsible for interacting with Twitter I want to expose a public method that the consumer of my API can work with. This is a similar way as we exposed using the module exports in Node.JS but we need to take into account that this is operating in the browser so we need to use the define function with inside RequireJS. Again, I'm going to take a dependency on jquery because I want to use the jquery Ajax methods. Like the Require method all the dependencies that we specify are going to be provided as arguments to the call back function that is to be executed. Because this is going to be an API I need to expose some public methods. So what I'm going to do is return a new anonymous object, expose a public method called timeline that is going to take a single argument called user. This will be the user name that I want to download the information from Twitter and then with inside this I'm going to return the jquery get json method so that the consumer of this API can then decide what they want to do when the Ajax request has completed. So here you see I'm using the dollars dot get json method so dollars being the dependency that came in through our initial define calling out to the Twitter API and including the user name and then providing a couple of other arguments just to clean up the data that is going to be coming back. So we come back to our main dot js file. I want to add the Twitter API as a new dependency. So to do that I add that to the array which is provided as the first argument to the require method. Because this is residing with inside a separate folder to my main.js file I have to provide a relative path. I also need to specify that this is an argument coming into our call back function. So now I have my Twitter API also available with inside the required js application. To use this I would just provide it the same way that we are working with jquery. So I'd do API.timeline, inside this I'd then provide the user that we have found through a jquery lookup and because this returns those dot get json object I can then operate against it as though I was operating against the actual jquery API. So I can provide through the done method a call back function. So inside the call back handler from our call out to Twitter or as far as my API is concerned, I call into a method called timeline I want to do some cleanup of the current UI and then insert the new data. The first thing that I'm doing on line 10 is finding all the existed Twitter information and just emptying out the done. I'm then going to iterate through all the tweets that came back from the timeline, create up a little bit of a html snippet, add that to an array and eventually push that entire array back into the done. So if we come back to our application within the browser, reload it and click load tweets you'll see that we get all the information that is being downloaded from Twitter. So as you can see here from the way that we've designed this application if we look back in Visual Studio we haven't explicitly specified any JavaScript files beyond jQuery and RequireJS with inside our cs html file. They've all been loaded as dependencies through the way our application is structured. Inside our main.js file we've said that we want to take dependencies on two objects one of those being jquery, the other being an API that we're exposing from elsewhere inside our application. We can obviously keep breaking this down into smaller components that are responsible through only certain parts of our application. But in the very least what we've done is we've extracted away the Twitter API from the main part of our application. This could have some other benefits that if we were doing unit testing of our JavaScript we could create a fake version of this as long as it exposed the same API and our main.js would not be any of the wiser. It should operate exactly the same.
Future of JavaScript modules
So now that we've seen two different approaches to producing modules within JavaScript it's important to talk about ECMAScriptvNext or you might be familiar with it under the name Harmony. ECMAScript is the foundation of the JavaScript language and at the moment the ECMAScript working committee is doing their best to solve this problem at a language level. The approach they are looking at is introducing a couple of new keywords to JavaScript as well as some new syntax. But the problem with this is it will not backwards compatible so browsers today will not be able to use the new module system that has been proposed. Currently this is still under review with the ECMAScript committee but it is still worthwhile being aware that at a language level there is attempts to solve this problem. Here's an example of what the proposed ECMAScript module system would look like. You notice on the first line we're defining that we have a module named math and then with inside that we're specifying a couple of exports. We want to export a function called sum that takes two arguments and then adds them together. We're also exporting a public static variable called pi, which will just be assigned to a value that represents pi. You'll see down a bit further that we are then using an import keyword and then using a new syntax to specify what we want to import from our math API. What you'll see is that we're specifying that we want to import the sum and the pi property from the math module and then these become available inside our API so we can use these as though they were global objects. As I said, this is still under review with the ECMAScript working committee but it's worthwhile being aware that it is a potential for the future of JavaScript. So just to recap this module what we have seen is two different ways that we can approach doing module-based development in JavaScript. We've seen the way the Node.js implements it which is using a CommonJS design pattern and this works by specifying the path to a module that we want to load. In our case we wanted to load our calc.js module. Inside of the module that we want to expose an API from we used the module.exports object and then we assigned the exports to any public methods that we want available from consumers of our API. Next up, we looked at RequireJS, which is an implementation primarily designed for browser based module development which takes a slightly different approach to CommonJS as it needs to take into account some limitations of working with a browser. We've seen that we have the require function and this takes in a collection of dependencies as an argument to it that says, I want to load in all these particular dependencies for this application that I'm producing. We've also seen that we can use the define function that also allows us to take in a set of dependencies, but ultimately will expose a new API back to anyone that wishes to consume it. There is a lot more that can be achieved with RequireJS. As I mentioned, you can use it for loading in html and CSS. We've also seen that the ECMAScript working committee is looking at how they can bring language support to module development as it is a common feature that is required in today's modern JavaScript applications.
Pub/Sub Design Pattern
Introduction
In this module we're going to look at the PubSub design pattern. In JavaScript, a lot of actions are driven by events. You'll be used to this if you are working in the browser with events such as click, change, submit, and the different actions that be performed by dom elements. But how do we handle this when it comes to the logical side of your application? Say you've got components you want to interact with each other, how can they do that? The best way is using a PubSub library, and this can help you bridge the gap between disconnected components within your web application. The way this works is you'll have some piece code in your application, which will raise an event and then n number of pieces of code within your application that will react to that event happening. The primary goal of this is to provide a disconnected communication model between the components within your web application or your Node.js application. You may be familiar with this if you're coming from a .net programming background as this is commonly done in .net using event-driven development. You'll have a piece of code on the page, which raises an event, and people can provide subscribers to that particular event. Let's think about how we would implement this in a traditional web application. Say we've got some kind of a store for our application, and we have two components on that, a product list and a shopping cart. We need to perform some level of communication between the product list and the shopping cart so that the user's actions can be reacted to. A common action could be something like clicking "add to cart." What we see here is we click "add to cart," the product list will raise that, and then send it over to the shopping cart which then will handle it, but it does raise an interesting problem. What if we were to display multiple shopping carts? Where does this "add to cart" action happen? Who's responsible for it? And how do we integrate it with the multiple shopping carts within our page? What happens if we actually removed the shopping cart, say it's being developed by another developer in our team and we're focusing on the product list? We still want to be able to raise this event, but how are they going to be reacting to that? Because we don't have a component yet that is capable of doing it.
Traditional applications
So let's have a look at a demo of how we can do this using traditional communication in JavaScript. So here I've got a simple store application, and when I click the plus symbol, I want to update the shopping cart with the item that has been added as well as change the icon from being a plus to a minus so that we can then later click that again and remove them from the shopping cart. Within this application, you'll see that we're showing the shopping cart in two locations. We're showing it once on the left hand side of the screen and once on the upper right hand side of the screen, and every time we click the "add to cart" option, it should update in both locations. Similarly if we click the "remove from cart" option, it should remove a value from the product list as well as decrement the value of our cart. Let's have a look at how we're implementing this. You'll see that I have a (inaudible) file, which has a side bar in it, which contains our shopping cart, so that I'm including a JavaScript file that is to our application, and lastly, I have an ordered list of products, which are appearing, within our application. If we jump over to our JavaScript file, you'll see that I'm implementing this using RequireJS, which you might be familiar with from the asynchronous module definition pattern that we looked at in a previous module, and within this, I'm doing several different things. First off, I'm finding the product list on line 6 and attaching an event handler to all the icons within that for the adding and the removing of the cart. You'll see inside this header, we're checking to determine whether or not we need to be removing an item from our shopping cart or alternatively whether we need to add an item from our cart. You'll see on line 17, we're building up a new element to put into our big shopping cart, which is the name of the product that we have just added. Similarly, on line 26, we're finding that item and removing it, and then on lines 31 and 32, we're updating the value of items within our shopping cart. So this piece of JavaScript is actually doing several different things with several different only slightly related pieces of functionality on our page. It's dealing with the click handler from our items in our product list. It's then also dealing with the individual shopping carts that we're displaying on our application. So what we've got here is something that is breaking the traditional goals of single responsibility. We have three different pieces of functionality. They are all being handled within this single Javascript file. So this could become a bit of a problem for maintenance down the track as we can have this file will grow larger and larger as we require more functionality from each of the individual shopping carts or if we were to require some additional functionality such as calling an AJAX request to say that we've incremented our cart and to add that into our back in system. It also raises the issue of what if we wanted to have multiple developers working simultaneously on the different features of this website. Say someone is responsible for the large shopping cart, someone else is responsible for the small shopping cart, and someone is responsible for the product list. Because this is all contained within the single file, we can quite easily get conflicts while each of us is trying to work on it.
Pub/ Sub overview
So now we see how we can produce a standard JavaScript application to do some interaction with various components on a webpage, where does PubSub enter the mix? The reason we would use PubSub for this is we want to be able to refactor out each of the individual components into their own separate logical blocks. This means that we've got a big of break in responsibility for each JavaScript file. We could have one specifically for our product list and then individual ones for the shopping carts that we're also displaying on our application. What we would then want to do is use some kind of a message or some identifier to provide information from one of these components to another, essentially raising an event that is not tied to any particular dom element, but just an event that has happened within our application, and this is where I say it's fairly similar to what you might have come across in .net programming by using event-driven development.
Creating a Pub/ Sub library
So let's have a look at prefecting this existing application to be using PubSub. So the first thing I want to do is create a new JavaScript file for our PubSub library. So I'm going to call this file pubsub, and within inside that I'm going to use RequireJS to expose a pubsub API. My pubsub library is not going to have any dependencies on any existing functionality because I want this to be an isolated little piece of JavaScript that can be run within our application. So I'm not providing any dependencies as a first argument for define. I'm just providing the function, which is going to be creating the object API. The first thing I want is some way that I can push the message id's and then the handlers for each of those messages into our JavaScript API. So I'm going to start off with a simple little cache object, which is going to use an empty Javascript little because we can add properties to that as required in our pubsub API. Now I've defined my simple return object, which is exposing the API that I want for my pubsub. I've created two methods, one called pub and one called sub, both of them taking a first argument, which is an id, which will be some way to identify a particular message within our PubSub system and with the sub on line 8, we're passing in a callback function that we want to execute. Let's start off by implementing our publish method. The first thing I want to do is I also want to allow people to provide in as many arguments as they want to be passed into the actual callback handlers that are being executed. So I'm going to use a little trick in Javascript through the arguments object to access the arguments that are being passed in that were not the id parameter. On line 6 what I'm doing is creating an empty array so I can access the slice method. From the slice method, I'm going to be invoking call, which allows me to provide through this context for the function that's being executed as well as any arguments that are to be passed to it. So in this I'm providing it with the arguments object, which comes through in the JavaScript function, and I also want to say I want to slice everything from Index 1 onwards. Because the arguments object is actually not an array, it is just an array-like in JavaScript, doing this allows me to perform operations and return it as an actual array essentially converting it into an array so I can get back all the arguments that are being provided to me. The next thing I want to do is see if this message id has been used before. If it's the first time this message id has been used, I'm going to create a entry with inside (inaudible). On line 8 I'm checked to see whether there is a property of our cache object that has the name of the id that's being passed to us, and if it's not, I'm just going to create an empty array which callback handlers can be assigned into at a later date. Lastly, I'm going to finish off by going through all the callback handlers and executing them with the arguments that are being provided to this function, essentially invoking the publish operation. So here we have the completion of our publish method. From line 12 to 14 what we are doing is going through all the functions that have been provided with inside our cache object for this particular message id and then using the apply method to invoke them passing in a null discontext because there's no relevant context for this particular operation, as well as the arguments that have been provided to be passed through. The reason we're using apply in this case instead of the call like we did on line 6 is because apply allows us to pass in an array of arguments instead of having to comma separate them as you do with call. It just means that we can provide an unlimited number of arguments without actually having to know what that argument structure would look like. So now that our publish method is completed, we should have a look at implementing our subscription method so that we can actually apply callback handlers to a particular message id. Like we did in our publish method, I'm going to check to see whether the cache actually exists for this particular id, and if it doesn't, I'm going to create a new cache and add the function to it. In the else condition, if there is already a cache for this id, so someone else has either subscribed or the message has already been published to this cache, I want to be just pushing this new callback handler into the cache. So that's the description method completed. What we are doing is checking to see whether this is the first time the cache has been used, and if it is, creating an entry in our cache for this message id, otherwise appending to the existing message cache.
Refactoring our product list
The next thing I want to do is refactor out my product list so that it's within its own separate JavaScript file, so the functionality for the product listing is kept completely isolated from other sections of our application. Again, I'm going to use RequireJS to define this piece of functionality. This time I want to take a dependency on the PubSub (inaudible) as well as jQuery because this is going to be required for our product list. I'm going to make this act as a bit of a bootstrapper. So rather than just doing any functionality directly with inside this, I'm going to be providing a method that will set up all the functionality of the product list. This means that any consumer of the product list can decide when they want to actually execute things like the attaching of the callback handlers. So I'm just going to provide an (inaudible) method. Now I want to come back to my original product.js file and copy the contents that was originally in there over to the new file. Here I'm going to then refactor it out so it is only specific for what is required of the product list itself. You'll see that I've considerably reduced the amount of code that is with inside this product list. No longer is the product list tracking the number of items that are in the shopping cart because it's not responsible for that. It's not a shopping cart itself, so it shouldn't need to worry about how many items are in there. I've also removed any of the code that was responsible for updating the shopping cart because, again, the shopping cart is not the responsibility of the product list. There'll be something specific that will be handling that itself. Now what I need to do is enter my calls into the PubSub library so that people who want to be aware of an "add to cart" event will be able to subscribe to that. The first thing I want to do before I actually write the calls into our PubSub library is create an item that will be representative of the value that is being passed in or the item that is being operated against. So here in line 8, I've created a very simple little JavaScript object that is going to represent the item that is going to be interacted with. It's going to have an identifier itself so that anyone who needs to be able to uniquely track it can track the particular item as well as having a name so that consumers of my UPI can update the UPI to indicate that something has happened. This is obviously just a JavaScript object, and although I'm using say, for example, the id is represented by the dom element that the user has clicked on as assigned in line 9, this shouldn't be of concern to the consumer. It's just we are providing a property called id that they can issue that's going to be unique. On line 14, I've made a call into our PubSub library. You'll see that I'm using the PubSub variable that has been passed into the function callback through RequireJS, and I'm invoking the pub method on it. I'm using a key of "add to cart" so that this can be uniquely identified by anyone that wants to consume it and then passing in an argument called item. This is the item that we've defined up on line 8 and will represent the information that is required by anyone who's consuming this API. I could alternatively deconstruct this object so that we pass in the id and the name separately, but for this example, I just wanted to combine them into a single object that could be used by anyone who's consuming this. I also want to create a way for people to listen to a remove from cart operation, because if you remember from our UI, when we click the minus sign, it should remove the values from the shopping carts on the screen. On line 21, I've done a similar thing as we were doing on 14 except I'm using an id of "remove from cart." This means that we can have separate event handlers subscribed to removing an item as we are to adding an item. I must be passing in the same item as the second argument to this so that consumers can listen for that particular item and react accordingly. Obviously these id's can be changed as long as anyone that is subscribing to them is also aware of the change. It's essentially a contract that's being created between product list and anyone who wants to listen for it. Now that we've refactored out our product list, we need to actually create our two shopping carts so that they can be interacted with as well.
Refactoring our carts
First off I'm going to create our big cart so the cart that appears in the left hand column of our screen. Again we're using RequireJS. I also want to include the PubSub and jQuery dependencies. With inside our shopping cart, we need to attach to the two messages that are being raised by the product list or that could be raised anywhere within our application and track some information that is happening with those. First thing I want to do is create an object which will represent this particular shopping cart, and I also want to create a variable which will track the number of items that are within it. Again, like the product list, I'm going to use the define method and expose a public method. Inside our inner method, all we're going to be doing is defining a dumb element that represents the big cart and assigning it into our variable that is captured through closure scopes. This just means that we've got a single location that the shopping cart will be defined with inside our JavaScript and we don't have to keep querying the dom to refind it. The next thing we need to do is listen for the "add to cart" that's being raised. We do this by using the PubSub (inaudible) subscription method. First off we need to provide it with the message id that we want to listen to, and then we want to provide it with a callback handler that will be operating against this message. As you remember from our product list, the contract states that we're going to be providing a single argument, which represents the item that has been added to the shopping cart. I'm going to add this to our function so we're including that within the arguments. Next, I want to just review back through our product.js file to what functionality was specific for the big shopping cart on the screen. On lines 17 and 18, you'll see that we're taking the name of the item that was added to the cart and appending that to the unordered list, which represents the items that are within our shopping cart. You'll also see on line 32, we're adding the updated count number to the UI so that we've got an accurate representation of how many items are within our shopping cart. So I'm going to replicate this functionality with inside our subscription method. I'm going to start off by incrementing the count variable, and then I'm going to find the header element that we're updating the count within. Previously I was just using a loose jQuery selector on line 32 to find the (inaudible) element, but because on line 30 we made a capture to the actual shopping cart, I'm just using the find method of that to then update the html. I don't have to do a full query of the dom to find that. Also we need to add the name of the item into our shopping cart. From line 9 onwards, what I'm doing is creating an empty LI element using jQuery assigning the html of that to be the name of the item that is provided to us through the PubSub event, and then finally I'm adding a key, which will be that of the item id. This will just make it easier so when we want to remove the item later, we can easily locate it within the list of items that have been added to our shopping cart. Now that we've created the "add to shopping cart" method, we need to create the "remove from shopping cart." Again, we're going to use the PubSub's subscription method, and this time we're providing the key of "remove from cart." Again, we're going to be taking the item that gets passed in so that we can use that inside our handler. If we review back to our products.js file, the original source that we are refactoring, you'll see that we're doing things such as decrementing the count value, which is happening on line 20, and then on line 26 onwards, we're removing the list item that represents the item from our shopping cart that has just been removed from the shopping cart listing. We're doing this by matching a data item against that that appears within the element. This is why on line 11, I captured the id of the item that is being passed into a data attribute called key, making it easier to locate during our remove functionality. So the first 3 things we need to do with inside our remove handler is decrement the cart count as well as update it with the new value. Next we're going to iterate through all the list items that are listed within our shopping cart, sorting them using the data attribute that matches the id that was passed in through our list item and then remove it from the dom. So you see that the functionality that we've got here is similar to what we had in our prodct.js file where we're removing the items, adding the items, and updating the count except now we have this with inside a file that is specifically designed to work with the big shopping cart on screen. It is not concerned with the actual product list itself, nor is it concerned with any other shopping carts that may be displayed. Lastly we want to create a functionality for the mini cart that appeared in the top right hand corner of our screen. There's a lot of similarities between the big cart and the mini cart, so I'm going to copy the code from the big cart over to the mini cart. On line 28, I'm going to change the dom element that we're looking for to be mini cart instead of the big cart, and I'm also going to be removing all the code that was responsible for adding a list item as that's not relevant with the mini shopping cart that appears on the screen. I'm mostly going to be changing lines 7 and 38 because instead of using a (inaudible) in the mini cart, it just uses a span tag. Lastly because we're only concerned about incrementing and decrementing the value in the shopping cart, we actually don't need to be taking in the argument to our two headers. So on lines 4 and 10 I'm going to remove item from our function. So now we've finished refactoring all our code into three separate files. We have a file that's specific for our product list, we have one specific for our big cart, and we have one specific for our mini cart. We can go back through our product.js file and refactor it to no longer be handling all the functionality that we previously were, and instead it can just be responsible for setting up all the other shopping carts within our application. What I've done in line 1 is I've added the big cart, the mini cart, and the product list all as dependencies that are required for the application. I could then call the (inaudible) methods on each of the to execute their bootstrapping code so that they can finish their own setups. The reason for doing it this way is that we only have a single place where we're using a dom ready event. If we come back to our browser and reload the application, you'll see that it looks exactly the same as it was because we haven't done any UI changes. If I click the "add to cart" or the "remove from cart" option, you'll see that we're still getting the exact same operations that we were previously getting. You'll see that both the left hand shopping cart as well as the upper right hand shopping cart are incrementing their values as we would be expecting.
Supporting unsubscribing
The final thing that we want to do in our PubSub API is implement a way that we could actually remove a callback handler. This is useful if we want to remove a section from our application so that the UI will not be still trying to listen to events when they're no longer relevant. To do this, I'm going to create an unsub method. This will perform the unsubscription operation that has happened within our application. The first thing I want to do is check to make sure that id has been passed in to identify which message this function would be belonging to. If there hasn't been an id, then we want to just immediately abort as there is nothing that we can be doing. Now that we've ensured that an id has been passed in, we want to determine whether a callback handler has actually been provided. We want to make the assumption in the API that if no callback handler has been provided that all of them are going to be removed from the PubSub API. If a particular function has been removed, we want to determine whether or not it is actually one that is known about within our subscription list, and if it is, we want to remove just that individual one. The first thing I want to do is look up for the index of this particular function. We're going to do a check to make sure that the index does actually match an item within our array. So if it returns something greater than negative one and assuming that it has, we want to remove the particular item from the array. Since JavaScript doesn't have an array remove method as you would be familiar with in .net programming, we have to do a bit of array trickery to actually remove the item at a particular index. The first thing that we have to do on line 34 is split the array from index 0 to the index of the callback handler that we've discovered. The next thing we're going to do is we're going to concat the rest of the array back into that array the original array split and then assign that into our cache. So the second half of the operation on line 34 is we perform a slice again, but this time we use a start index of the index of the array plus 1 and then don't provide a second argument, and this will tell JavaScript to take all the rest of the items within the array, so take the items from one after the current handler to the end of the array. So that's how we cam implement the unsubscription method as well with inside our PubSub library.
Extending Pub/Sub
So now that we've seen how you can refactor an existing JavaScript application to use PubSub to communicate between the components and have only a single responsibility for each JavaScript file, we want to have a look at how we can take this idea a little bit further. With JavaScript, if you're not being very careful, you can accidently load scripts in an unknown order. This could mean that we're publishing a message before the subscribers have actually been registered. This means that we could be losing potential information because the subscription doesn't know that it has already had an event fired to it because it was never there in the first place. So what we can do is involve the PubSub library to be a bit more like a message bus. This will allow like bound subscribers to receive messages that have already been published, essentially create a kind of history stack to our PubSub API. This can be very useful when we want to lazy load components within to our Javascript page, say if you're building a mobile application or a single page application, you could be only loading in the components that make up your page as they are required. A scenario for this would be if you are adding the shopping cart late in the page life cycle, someone could've already clicked the "add to cart" link before the shopping cart has actually been included. So you'd still want the shopping cart to react to that prior click. Another good advantage of this is it can improve performance. (Inaudible) you could do with the (inaudible) execution pattern that we saw in a previous module. So let's have a look at extending our PubSub library to be a bit more like a message bus. We don't want the consumers of our PubSub library to be any the wiser that this is actually acting like a message bus, so the refactoring is ordered to take place inside our pubsub.js file because it's only specific to the pubsub library that we want to perform those changes. The first thing I want to do on line 9 is change it so that we're just using a simple array to represent the cache object. Instead, I'm going to change this to a JavaScript object that will have two properties. The two properties of my PubSub library are going to be callbacks, which will represent all the subscriptions, which have happened to a particular message id, and the second will be args, which will represent the arguments that have been passed in each time the PubSub API is used to evoke the pub method. The next thing I have to do on line 15 and 16 is exchange that so that we're not trying to go through the cache as an array instead of reusing the callbacks property and treat that as an array, which it is. The next thing I need to do is I need to update lines 21 and 23 to use a new cache object structure. You'll see that on line 21 and 26, we've now got the same object structure that we have in our pub method, but we also need to add another piece of code to our subscription method. Because the subscriptions may happen after a publish method has already occurred, we want to access all the arguments that have been provided previously and go through that array. By doing so, we can then invoke the callback handler that has been provided as the fn argument to the subscription method and execute it with the arguments that were provided. This is similar to what we do on line 15 inside our pub method, but rather than going through the callbacks, we're going to go through the arguments. On line 30 what you'll see we're doing is we're going through the arguments with inside a fall loop that have provided as previous invocations of this publish, and then we're going to execute the current handler and provide in those arguments to it. This will be acting as our little bit of a history that occurred with inside our API. Finally we need to update our unsubscribe method as well. On line 40 what we're doing it changing the structure of our object to match the known structure that we have and then instead of operating against the cache as though it was an array, we're going to be interacting with the cache callback's property on lines 45 and 48 to do our array manipulation. If we come back to our browser and reload the page, you'll see that this is operating in exactly the same method that it was before. We haven't changed any of the operations in the way that has been breaking. We've just been doing incremental refactors to make sure that our API is as flexible as possible. ( Pause )
Recap
So to recap, what we've seen here is how we can take an existing application that has been written in a way that could be potentially hard to maintain in the long run because of tight coupling between components and break that down across multiple smaller component files. We then refactored the code so that we're using PubSub to communicate between each component on the page, making sure that they only are responsible for what they should be responsible for and that they have all the data that they are actually going to be requiring within. We finished off by refactoring our PubSub to be a little bit more advanced and handling some historical data as well so that if an operation happens before any of the handlers are actually subscribed, it could still react to that in a way that our application will not be any the wiser. Ultimately what we've done is we've taken the idea of event-driven programming, which is very common in JavaScript, and raised it up to our application level rather than just keeping it at our dumb level.
Promises
Introduction
In this module, we want to look at the Promise and Deferred pattern in JavaScript. In JavaScript, as you're likely aware, everything happens asynchronously. If we want to do something such as query off to an AJAX service, we have to wait for a call back to be executed before we could react to that. Similarly, if we want to do some animation, or many other operations that could be happening. So how do we actually deal with these deferred operations? How do we know when our AJAX action has completed? How do we know when our animation has finished? Or how do we know that any of the other different operations that could be happening within our application have been completed, and more importantly, what if we had dependencies on several of these actions executing at the same time? This is where the Promise and Defer concept comes in. Promise and Defer work primarily through a deferred object. A deferred object is something that will actually handle the entire action that is being performed. It is the core of what's happening. There's three different things that could happen during the duration of a deferred object. A progress event can be raised to inform the application that the action they're awaiting is still running. A done event will be raised when the deferred action has successfully completed its operation. This could mean that an AJAX response has come back with a response of 200 and there is data ready for consumption. And finally, a failure event can be raised. This is what happens when the deferred action has been unsuccessful. So, for example, a survey error has happened on your AJAX request. It's obviously been unable to fulfill that. It's come back with a 500 error response code from the server so a failure could be raised back to your application. Finally, the (inaudible) of a deferred is that anytime you reaccess the same deferred object and there was some data in it, it shouldn't change what was originally given to it. This means that you could store off the result of a deferred action for later use and keep coming back to it and always get the same data and be able to perform the exact same actions with your application being none the wiser. This allows for some smart caching, particularly with regards to AJAX requests. You can put some smart caching around whatever you're doing and making sure that you're only actually pulling down new data if and when you need it.
A simple Promise API
So let's have a look at how you would go about implementing a very simple Promise API in JavaScript. So here I'm going to use a little Nodes.js application that I've got and I'm going to create a very basic Promise API and just some sample usages of it. You'll remember from our previous module on asynchronous module definitions and now Nodes.js does this that in the first line we're requiring our Promise API. From here I'm creating a new instance of our Promise and then throughout the rest of this application I'm going to be doing some different actions against it. You'll see on line six, I'm going to be telling the Promise that it has resolved. So this is being done through a set timeout of one second just to pretend that this is an asynchronous operation that has happened. On line 11, I'm doing an example of what would happen if I was to add a handler after the deferred object has already completed. I would be expecting this handler to execute because, as I said, the Promise has stated that it should continue to return exactly the same response once it has completed. It should never change itself. You'll see on line 16, I'm explicitly adding to the Promise a done handler that I want to execute as soon as that Promise has completed. Because that Promise is being simulated as an asynchronous operation, it would have completed by the time this has been executed. On line 19, I'm creating a second Promise just so we can do some different operations with it. This time I'm adding both a failed and a done handler so that I can see what will happen if a failed event happens for my Promise API. If a failure happens, I would not expect the done handler to be executed - only the failed one. On line 28, I'm telling my second Promise to fail itself. And I'm doing this in a set timeout of one second again just to simulate an asynchronous action. Finally, I'm going to log out to the console that our application has completed its execution just so I can see the event stack as it happens. The order of information that I would expect to be output would be the application completed message followed by the message from line 16, the message from line 22, and lastly, the message from line 11 because that action is waiting two seconds to execute so it should happen after all other actions have happened on this. You'll also notice on line 23 I'm doing some method chaining which you will remember from an earlier module where we looked at some common JavaScript object patterns. If I come over to my Promise API in the Promise.js file, you'll see that I've again created this as a Nodes.js module finishing off with module.exports equals Promise which is the object we're creating within this. You'll see that there are four methods being defined; two which take a function which is going to be the handler and two which are going to actually perform the action. For brevity of this example, I'm not covering the progress event but you should be able to extrapolate how that would be done throughout looking at the implementation of these two other operations. To get started implementing our Promise API, I want to create a couple of variables that are going to be used with inside our closure scope. I want to create a variable to hold some data which could be passed in from our resolved and failure methods. I want to be able to capture the handlers that are being passed to done and failed. And lastly, I want to track the current status to make sure that once we have completed either successfully, or unsuccessfully, we no longer continue on in our operations and we cannot refail if we've already failed. So I've created a couple of empty areas here on lines three and four and on line five I'm saying that the current status of this Promise is progress, meaning that as soon as you create a new Promise the action that you're performing is currently in progress. With inside our done and failed handlers, let's have a look at how we could implement our done handler now. The first thing I want to do is capture the function that has been passed to it and put it into our collection of done handlers. Secondly, I want to check to see if the current status is that we've already completed and completed successfully. If that's the case, I just want to execute this handler because the action is completed and we're not going to get this method raised internally from our API. I'm going to pass in the data to the handler that has been executed so that we can get the capture of that in a much more in depth implementation of a Promise API. You would possibility want to be making a clone of the data object to ensure that it is imputable so that it is always the same when additional handlers are added. Lastly, I want to return the Promise API again so we can perform our method chaining. To implement the failed handle, it's very similar to the done but obviously pushing it into a different area and checking for a different status. Now to implement our resolve and fail methods. These two methods allow us to programmatically finish off our Promise so say our AJAX response has come back we would want to be calling out to all our done handlers to make sure that they get executed and that they can receive any data. The first thing I want to do is check to make sure that we are still in the progress state. Because if we're in the progress state, we can successfully resolve our Promise. But if we're not in the progress state, we've either failed already or we've successfully completed already. And in either of those scenarios, we're unable to re-resolve the Promise with a new status. So in the case that we've already completed or the status is no longer in progress, I want to throw in a new handler exception so the contributors of our API will be to react to that in that way. Assuming that we are still in the progress state we can now set the status to done. We want to capture any data that was passed in as that result object to this function so that it can be provided to all the call back handlers that are listening. Finally, we want to go through the collection of done handlers and invoke them. So as you can see on line 35 to 37 what we are doing is iterating through the done handlers that were previously provided and executing each one in sequence. We finally finish it off on line 39 with returning the current instance of the Promise API allowing our method chaining to continue onwards. To implement the failure -- to implement the fail method, it's very similar as we have in the resolve, but obviously setting some different statuses and selecting from a different area. So now we've completed our implementation of a very basic Promise API. If I come over to Nodes.js, if I come over to a console window and use Nodes.js to execute this, we should get the execution order that we expected by receiving the appropriate console log messages. You'll see that we received the application completed message, which is the first one that we were expecting. And then we received the deferred object has completed followed by the failure message and then lastly the same message was provided in the handler that was like-bound to the original deferred object. You'll notice that the message on line 24 never got logged out to the console and that is because the second Promise was unsuccessful and this message should never have been received, which it wasn't.
Promises with jQuery
So now that we've seen how we can implement our own Promise API, let's have a look at an existing one. jQuery has had the deferred API within it since jQuery 1.5 and it's starting to become very commonplace to be used with inside the library itself. Deferred is primarily used with inside the AJAX methods of jQuery allowing you to do chaining similarly to what we were doing just then. Another thing with the jQuery deferred object is that this is publically available from the jQuery API itself allowing you to use it with inside your own libraries in any way that you see fit.
Demo: jQuery Promise
Let's have a look at an example of how we can use the jQuery deferred object. Inside our demo for the asynchronous module definition that we used a custom API to expose some access to performing a Twitter search operation. When we're doing this we're actually inadvertently using the jQuery deferred API. If we have a look at the API JavaScript file that we created, you'll notice how we did return dulls.getJSON. What this actually returns is an instance of the jQuery deferred API. And this why back with inside our main JavaScript file we were able to do .done on line seven and pass in the call back handler. This is the most common way to do these kind of operations within jQuery rather than passing the call backs in as second or supplementary argument to anything we're also passing in for the API. This means that we're avoiding a little bit more of the so-called Christmas tree scenario where we end up with method call backs with inside method call backs and a large Christmas tree-like effect of indentions with inside our JavaScript. But what is interesting about the jQuery deferred API is, as I said, you can use this yourself within your own applications and your own libraries without having to be tied to say an AJAX request. If you've just got an operation that you want to perform within your library that you believe people will ant to tie into once it has successfully completed, you can do that quite easily. Another interesting thing you can do with the jQuery deferred object is use the dollars.when method that's provided by the jQuery API to then also trade up a series of deferred operations. And then once they have all completed, either successfully or unsuccessfully perform a single action against those. And that's what we're going to do. We're going to start off by creating a little JavaScript plugin. I'm going to add this to the top of my main.js file for our jQuery plugin. What we're going to do is create the JavaScript equivalent of the blink tag inside our plugin. What I've done is I have allowed the user to pass in some custom arguments; one which will control the frequency that the blink occurs and the other which will control the number of times a blink happens. And then merging this with some default values and then setting up some other variables that I'm going to be requiring within. The most important one is on line 8. I'm creating a variable called dfd, and this is equal to dull is.deferred. What this does dull is.deferred will create me a new instance of the jQuery deferred API meaning that I can perform a similar series of actions as we saw in our Nodes.js example but a bit more complete as opposed to the simple example of what we created. Because I want to be able to chain together my instances of deferred objects and provide handlers to when they're completed, I need to finish off this plugin by returning the jQuery deferred object. So on line 10, I am returning dfd.Promise. What this does is this returns the Promise API that has been created within jQuery. This allows me to provide the done failed success call back handlers that could be useful for people wanting to consume my API. Now let's come down to a document ready event and do some refactoring so that we can combine our blink operation with a call out to our API. As I said, jQuery has an easy way that you can chain together multiple deferred actions using the dollars.win method. The first thing I want to pass into dollars.win is a call to API.timeline. Secondly, I want to do a blink operation of the input tag the user name that has been provided to Twitter is stored within. I'm going to say that I want this to blink twice. Dollars.win returns a very similar API that you would be expecting if you're working with the deferred API itself. So to provide a call back handler that will be executed when both of operations have successfully completed, what you need to do is use the done method. The done method will actually provide not the arguments of any particular call back handler but it will be provided with all the different call back handlers result arguments. So rather than having the tweet subject being pass in on line 18 as we have here, we have to change this to a bit more of a generic object. We can then access the tweets. As the first argument that has been provided in this variable. The reason for this is that API timeline is the first method that was passed into dollars.win. If we come to our page and reload and click the load tweets button, you'll notice that nothing has happened. If we happen to look in the network tab of our developer tools in the browser, you'll see that we've made a call into the user timeline as was to be expected and that if we expect this, you'll see that we did get a response that came back. But we didn't end up getting anything output on the screen. If I come into my JavaScript tools, you'll see that I've also set a break point on line 19 which is the first line of our done handler and even when I click the load tweets, I never get this line executed. The reason for this, if we come back to our JavaScript file, while there we can specify that we have a deferred object with inside our blink plugin. We've never said that that has successfully completed. Because it's never successfully completed, jQuery cannot say that the dollars.when method had all its provided handlers successfully done. So although the API.timeline call was successful, the subsequent call is yet to be successful so we cannot continue on into our done handle. So we come back up tour blink plugin. We need to implement it so that we will actually call dfd.resolve when have successfully completed some operation. I'm going to make the assumption that once we have blinked the required number of times, in this case, we've said that we wanted to blink twice, we can class this as successfully completed. Obviously, the default number of times to execute is negative one so if you don't provide that, we may never have the done handlers executed because we may never successfully resolve. To handle the functionality inside a blink plugin and to make sure that the blink actually happens, I'm going to create a new function called go. This will just be used within a recursive set timeout pattern so that every specified frequency, in this case the default one second, we will execute the blink operation. On line 14, I'm just executing the go method initially to kick off the whole process. The first thing I want to do with inside my go method is handle a failure state. For a failure state I want to be treating the lack of elements found by the provided selector or the providing jQuery object having a lack of elements. I want this to be treated as a failed state. So to do this and to make sure all the failed handles are executed correctly, I'm doing dfd.reject. This will tell the jQuery deferred object to handle this as a failure and all the fail handlers should be executed. For success I want to check it against the variable which I've defined on line 6 against the count required for this blink operation. If they match, I want to return a successful deferred object. And I do this using the dfd.resolve method. Finally, assuming that those two conditional segments don't produce an outcome, I want to increment the number of operations or the number of times through this blink as well as actually do the blinking itself. On line 20, I'm going to use the jQuery fade in fade out methods to do the transitions to simulate the blinking and I'm going to tell it to do this at 50% of the frequency of the timeout. This is because I will be able to complete both the fade in and fade out throughout the course of the timeout period. On line 21, I'm setting up our recursive set timeout pattern so that we're re-executing this go method with a frequency that has been specified; either the default one second or a custom frequency that the user has decided that they want. If we come back to our browser and reload our page and now we click on the load tweets button. We should see the text block blink twice and then we should also have the tweets loading. And there we have it. We've chained together two deferred operations and it wasn't until they were successful that we were able to get the result that we were expecting. If we wanted to implement a handler for a failure state, say, pop-up a message to the user that one or more of our deferred has been invalid, we can do this using the failed method. Because the done method is nicely implementing its chaining, we can do .fail on the end of this and providing a call back handler. Inside this I'm just going to do a simple informing the user that something has gone wrong. To simulate a failure, I'm just going to change this selector on our blink. Rather than find element, we'll attempt to find something that doesn't exist. Now if we come back to our page, reload it and click on load tweets you'll see that received message because one of our handlers has failed. This means that we can combine both operations that we all have a dependency on that we want to execute at the same time.
Recap
So just to recap. The Promise and Deferred patterns within JavaScript are very useful as they are fairly similar to what we can achieve with pub sub but their designed with a bit more of an asynchronous operation in mind. They are very useful if you've got something that can be taking a long time to be progressing as you can provide actions that happen within the very state of your application. You can provide a notification of a progress to be happening, operation has complete successfully or a failure if one or more of the operations you're depending has been unable to successfully complete. We've had a look at how you can create one of these APIs yourself in a very basic scenario. We've also had a look at how you can do this with jQuery and take leverage of the jQuery.deferred API. Many other libraries also implement deferred APIs and if you've had a look at Win.js you'll notice that itself has an implementation of a Promise and Deferred pattern making very easy to do these kind of operations with inside an application as well.
Course author
Aaron Powell
Aaron is a Senior Developer and Technical Web Specialist with Readify and Microsoft MVP for Internet Explorer Development. Aaron focuses mainly on front-end web development, with a passion for...
Course info
LevelIntermediate
Rating
(1059)
My rating
Duration2h 2m
Released18 Apr 2012
Share course