Programming Javascript Applications

This book is not intended to teach you the basics of JavaScript. Instead, it’s designed to build on your existing knowledge and discuss JavaScript features and techniques that will make your code easier to work with over time.


Eric Elliott


253 Pages

29349 Reads

64 Downloads

English

PDF Format

8.55 MB

Java Script

Download PDF format


  • Eric Elliott   
  • 253 Pages   
  • 19 May 2015
  • Page - 1

    read more..

  • Page - 2

    read more..

  • Page - 3

    Eric Elliott Programming JavaScript Applications read more..

  • Page - 4

    Programming JavaScript Applications by Eric Elliott Copyright © 2014 Eric Elliott. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles ( http://my.safaribooksonline.com). read more..

  • Page - 5

    Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. The JavaScript Revolution. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . read more..

  • Page - 6

    Function Polymorphism 29 Generics and Collection Polymorphism read more..

  • Page - 7

    Model View Controller/MV* 114 Presentation and DOM Manipulation read more..

  • Page - 8

    HTML as an API Media Type 185 Jade read more..

  • Page - 9

    Preface Introduction There are many books on the web technologies covered in this publication. However, there are precious few on JavaScript that can be recommended to somebody who wants to learn how to build a complete JavaScript application from the ground up. Meanwhile, almost every new tech startup needs knowledgeable JavaScript application developers on staff. This book exists read more..

  • Page - 10

    We’ll cover: • JavaScript features and best practices for application developers • Code organization, modularity, and reuse • Separation of concerns on the client side (MVC, etc.) • Communicating with servers and APIs • Designing and programming RESTful APIs with Node.js • Building, testing, collaboration, deployment, and scaling • Expanding reach via internationalization Who This read more..

  • Page - 11

    JavaScript: The Good Parts, and pay special attention to Appendix A so that you can learn from the mistakes made by more experienced JavaScript developers. Unit Testing It’s difficult to overstate the importance of unit testing. Unit tests are used throughout this book. By the time you reach the end, you should be accustomed to seeing and writing them. As you practice the read more..

  • Page - 12

    Safari® Books O nline Safari Books Online is an on-demand digital library that lets you easily search over 7,500 technology and creative refer‐ ence books and videos to find the answers you need quickly. With a subscription, you can read any page and watch any video from our library online. Read books on your cell phone and mobile read more..

  • Page - 13

    Thanks Thanks @JS_Cheerleader for encouragement and lots of great JavaScript links. Thanks to Brendan Eich for his tireless work to drive JavaScript and the web forward. Thanks to the team at O’Reilly. To Simon St. Laurent, who immediately recognized the value of the book and provided a lot of encouragement along the way. To Brian McDo‐ nald, whose valuable feedback read more..

  • Page - 14

    read more..

  • Page - 15

    CHAPTER 1 The JavaScript Revolution JavaScript is arguably the most important programming language on earth. Once thought of as a toy, JavaScript is now the most widely deployed programming language in history. Almost everyone with a computer or a smartphone has all the tools they need to execute JavaScript programs and to create their own. All you need is a browser and a read more..

  • Page - 16

    In 2004, Google launched Gmail. Initially applauded because it promised users nearly infinite storage for their email, Gmail also brought a major revolution. Gone were the page refreshes. Under the hood, Gmail was taking advantage of the new Ajax technology, creating a single-page, fast, and responsive web application that would forever change the way that web applications are read more..

  • Page - 17

    Prototypal OO is so much more flexible than classical inheritance that it’s possible to mimic Java’s class-based OO and inheritance models in JavaScript virtually feature for feature, and in most cases, with less code. The reverse is not true. Contrary to common belief, JavaScript supports features like encapsulation, polymor‐ phism, multiple inheritance, and composition. read more..

  • Page - 18

    It was built entirely with the latest open web technologies.) Such functionality is powered by Ajax calls that do their thing in the background without slowing down the UI. Reusability JavaScript code, by virtue of its ubiquity, is the most portable, reusable code around. What other language lets you write the same code that runs natively on both the client and the server? read more..

  • Page - 19

    • An app server/content management system (CMS) to route requests and deliver pages to the client • A static content deliver network (CDN) for cached files (like images, JavaScript, CSS, and client-side templates) • The client (browser) To see how these generally fit together, see Figure 1-1. Figure 1-1. Infrastructure Most of these components are self explanatory, but there read more..

  • Page - 20

    Take this example message, describing a collection of books: [ { "title" : "JavaScript: The Good Parts", "author" : "Douglas Crockford", "ISBN" : "0596517742" }, { "title" : "JavaScript Patterns", read more..

  • Page - 21

    are free to implement the UI (or not) in whatever manner or language is desired. REST architecture does not address how user interfaces are implemented. It only deals with maintaining application state between the client and the server. RESTful web services use HTTP verbs to tell the server what action the client intends. The actions supported are: • Create a new entry in read more..

  • Page - 22

    3. Data is returned in the form of a document. Those documents are commonly text strings containing JSON encoded objects, but REST is agnostic about how you package your data. It’s also common to see XML-based RESTful services. Most new services default to JSON formatted data, and many support both XML and JSON. 4. The client manipulates the data representation. 5. The read more..

  • Page - 23

    CHAPTER 2 Functions Functions are the building blocks of applications. They are particularly important in JavaScript because JavaScript supports first-class functions, functions as objects, run‐ time function definition, and so on. JavaScript’s features allow you to use functions in ways that you may not be familiar with. It’s important to have a thorough understanding of how read more..

  • Page - 24

    solutions are cryptic. This tends to happen when a single line of code is used to accomplish more than a single atomic goal. Less Is More In order to aid readability and reduce the temptation to do more than one thing, functions should be as short as possible: Just enough code to do the one thing they were made to do, and no more. In most cases, functions should read more..

  • Page - 25

    }; // addItem gets triggered by an event handler somewhere: session.cart.addItem('grapefruit'); ok(session.cart.items.indexOf('grapefruit') !== -1, 'Passes: Session cart has grapefruit.'); ok(savedCart.items.indexOf('grapefruit') === -1, 'Fails: The stored cart is unchanged.'); }); Sadly, when the user adds or removes items from his session cart, those read more..

  • Page - 26

    Keeping things isolated in this way can also enhance your ability to implement state management. If the functions that manipulate data don’t have to worry about the state of the program and account for side effects created by other functions, they can do their job with much less code. All they have to know how to do is the one task they were designed to do. read more..

  • Page - 27

    'Grade should pass.'); }); What’s worse, this pattern fails inconsistently across browsers. It’s best to avoid condi‐ tional function declarations entirely. For more detail, refer to “Hoisting” on page 22 . Function declaration tends to encourage large piles of loosely related functions to grow in your module, with no real hints about what goes where, whether it’s read more..

  • Page - 28

    baz.f(); // => [Function] (Note: Also anonymous.) The baz example exhibits the same behavior. It’s another anonymous function assigned to a property in an object literal. Function expressions assigned to object literals are sometimes called method literals. Methods are functions attached to objects. The advantage is that method literals make it very easy to group related functions read more..

  • Page - 29

    Named function expressions are like anonymous function expressions in every way, except that they have a name that you can use from inside the function (for recursion). That name also conveniently appears in the function call stack. As with anonymous function expressions, you can use them anywhere you would use a variable—not just inside method literals. Named function expressions read more..

  • Page - 30

    ok(true, 'Declaration bar() should be called outside the' + ' expression.'); } testDeclaration = true ; } foo = function bar(declaration, recurse) { if (recurse) { ok(true, 'Expression bar() should support scope safe' + ' recursion'); read more..

  • Page - 31

    return result; }; test('Lambdas.', function () { equal(sum(), 15, 'result should be 15.'); }); The .addTo() function passed into .forEach() is a lambda. The .forEach() method calls .addTo() for each number in the array. Note that .addTo() has access to the result variable from the containing function scope’s closure (covered in more detail in read more..

  • Page - 32

    lambda is a function that is used as a value (assigned to a variable or passed between functions). Some languages support lambdas but do not support closures. All functions in JavaScript are first class, meaning that you can use them anywhere you would use a value, so it’s possible to create a first-class function that is not also a lambda. You can pass any function read more..

  • Page - 33

    // Implementation... }; Lightbulb.prototype.on = function on() { // Implementation... }; Lightbulb.prototype.blink = function blink() { // Implementation... }; test('Prototypes without IIFE.', function () { equal(lightbulb.toggle(), true , 'Lightbulb turns on.'); equal(lightbulb.toggle(), false , 'Lightbulb turns off.'); }); As you can see, this method leads to read more..

  • Page - 34

    'Lightbulb turns off.'); }); }()); Method Context Functions are invoked by appending parentheses to the end of the function reference. For these examples, we’ll use a slightly altered highPass() function: function highPass(number, cutoff) { cutoff = cutoff || this .cutoff; return (number >= cutoff); } var filter1 = { read more..

  • Page - 35

    result3 = filter1.highPass(6); equal(result1, false , '3 >= filter1.cutoff should be false.'); equal(result2, true , '3 >= filter2.cutoff should be true.'); equal(result3, true , '6 >= filter1.cutoff should be true.'); }); When you invoke a method with dot notation, you have access to the object’s proper‐ ties using this . The number read more..

  • Page - 36

    }, isOn: false }, toggle = lightbulb.toggle, lightswitch = document.getElementById('lightswitch'); lightswitch = document.getElementById('lightswitch'); lightswitch.addEventListener('click', lightbulb.toggle, false ); Glancing over this code, it looks simple enough. An event listener gets attached to the lightswitch DOM with .addEventListener() . There’s just read more..

  • Page - 37

    JavaScript builds its execution environment in two passes. The declaration pass sets up the runtime environment, where it scans for all variable and function declarations and creates the identifiers. The second pass is the execution pass. After the first pass, all declared functions are available, but variables are still undefined. Consider this code: var x = 1; (function () read more..

  • Page - 38

    (function () { function number() { return 2; } equal(number(), 2, 'Inner scope wins.'); }()); equal(number(), 1, 'Outer scope still works.'); }); Function expressions do not share this behavior, because they do not declare a function. Instead, they declare a variable and are subject to the same variable-hoisting read more..

  • Page - 39

    } number = function number() { return 2; } equal(number(), 2, 'number() is defined now.'); }()); equal(number(), 1, 'Outer scope still works.'); }); If you declare all of your variables at the top of your function, and define your functions before you try to use them, read more..

  • Page - 40

    try { ok(data, 'This throws an error.'); } catch (e) { ok(true,'The data var is only available' + ' to privileged methods.'); } equal( obj.get(), 1, '.get() should have access to the closure.' ); }); In this example, o is an object factory that defines the private variable data and a priv‐ read more..

  • Page - 41

    'arr should be [1,2,3]' ); start(); }; timer(); equal( arr.length, 0, 'array should be empty until the first timout.' ); }); }()); In this example, the inner() lambda has access to arr , complete() , and count from the containing function. Its job is to add the read more..

  • Page - 42

    You should be familiar with all of these techniques so that you can choose the right tool for the job. There are some principles to keep in mind when you design your methods. This bears repeating: • Keep It Simple, Stupid (KISS) • Do One Thing (DOT), and do it well • Don’t Repeat Yourself (DRY) Named Parameters The number of variables you pass into a function read more..

  • Page - 43

    'colorScheme stored correctly.'); }); In this case, the createUser() function takes five optional parameters. The userPro to object is a prototype (not to be confused with the prototype property). The trouble with this implementation becomes obvious when you look at the usage in isolation: var newUser = createUser('Tonya', '', '', '', 'dark'); What jumps out read more..

  • Page - 44

    Array.prototype.slice() is an easy way to shallow copy some or all of an array (or an array-like object). You can borrow the .slice() method from the Array prototype using a technique called method delegation. You delegate the .slice() call to the Array.prototype object. The method call looks like this: var args = Array.prototype.slice.call(arguments, 0); Slice starts at read more..

  • Page - 45

    + '.'); } test('Polymorphic branching.', function () { var test1 = morph('cats', 3), test2 = morph('dogs', 4), test3 = morph(2); equal(test1, 'The pet store has 3 cats.', '3 Cats.'); equal(test2, 'The pet store has 4 dogs.', '4 Dogs.'); equal(test3, 'The pet store has 2 turtles.', 'The pet store has 2 read more..

  • Page - 46

    return methods[action](args); }; test('Dynamic dispatch', function () { var test1 = greet(), test2 = greet('hello', 'world!'), test3 = greet('goodbye', 'world!'); equal(test2, 'Hello, world!', 'Dispatched to hello method.'); equal(test3, 'Goodbye, cruel world!', 'Dispatched to goodbye method.'); }); This manual read more..

  • Page - 47

    if an object has the features you need, assume it’s the right kind of object and use it.) Many of the built-in object methods are generics, meaning that they can operate on multiple types of objects. JavaScript supports two types of collections: objects and arrays. The principle difference between an object and an array is that one is keyed with names and the other read more..

  • Page - 48

    'randomItem works on Objects.'); ok(obj.hasOwnProperty(randomItem(arr)), 'randomItem works on Arrays.'); }); These tests check to see if the returned value exists in the test object. Unlike true generics, this code relies on conditional branching internally to handle objects as a special case. Since arrays are already objects in JavaScript, a lot of what you might read more..

  • Page - 49

    ok(i === 1, 'String methods work on numbers.'); }); Method Chaining and Fluent APIs Method chaining is using the output of one method call as the context of the next method call. For example, in jQuery you often see things like: $('.friend').hide().filter('.active').show(); Perhaps better: $('.friend') .hide() .filter('.active') .show(); This translates to: “find read more..

  • Page - 50

    There’s more to fluency than chaining. The salient point is that fluent methods are made to work together to express functionality in the same way that words in a language work together to express ideas. That means that they output objects with methods that make sense to call on the resulting data. Building a fluent API is a lot like building a miniature domain-specific read more..

  • Page - 51

    Instead, you could pass in a function to handle the comparison for the sort: var shows = [ { artist: 'Kreap', city: 'Melbourne', ticketPrice: '40' }, { artist: 'DJ EQ', city: 'Paris', ticketPrice: '38' }, { artist: 'Treasure read more..

  • Page - 52

    you don’t even have to think about writing a for loop. You frequently see a pattern like this repeated in most code: test('Traditional for loop', function () { var i, length = books.length; for (i = 0; i < length; i++) { books[i].category = 'music'; } ok(books[0].category === 'music', 'Books have read more..

  • Page - 53

    deepEqual(rotate(original), [2,3,1], 'rotate() should rotate array elements.'); // Fails! Original array gets mutated. deepEqual(original, [1,2,3], 'Should not mutate external data.'); }); Pure functions won’t mutate external data: var safeRotate = function safeRotate(arr) { var newArray = arr.slice(0); newArray.push(newArray.shift()); return read more..

  • Page - 54

    Partial Application and Currying Partial application wraps a function that takes multiple arguments and returns a func‐ tion that takes fewer arguments. It uses closures to fix one or more arguments so that you only need to supply the arguments that are unknown. Imagine you have a function multiply() , which takes two arguments, x and y , and you notice that you read more..

  • Page - 55

    An add function add(1, 2, 3) would become add(1)(2)(3) in curried form, where the first call returns a function that returns another function, and so on. This concept is important in lambda calculus (the inspiration for the lisp family of languages, from which JavaScript borrows heavily). However, since JavaScript supports multiple argu‐ ments, it’s not common to see true read more..

  • Page - 56

    Callbacks work great when you’re only waiting for one operation at a time, or when you only have one job to do when the response comes back, but what if you need to manage multiple asynchronous dependencies or you have several unrelated tasks waiting on the same data (such as a provider authorization)? That’s where promises can be very useful. Promises and Deferreds read more..

  • Page - 57

    to isolate those callbacks from each other so that the callback code can be organized independently of the initiating call. A deferred is the object that controls the promise, with a few extra methods. jQuery’s .Deferred() returns a new object that does everything a promise does but also provides .resolve() and .reject() methods that trigger the corresponding callbacks. For read more..

  • Page - 58

    setTimeout(function () { start(); }, afterTimeout + 20); cancelTimer .done(function () { ok(false, 'A canceled timer should NOT run .done().'); }) .fail(function () { ok(true, 'A canceled timer calls .fail().'); }) .cancel(); }); Promises really shine read more..

  • Page - 59

    anyway. This reminds me of a story from the MIT Lightweight Languages discussion list, by Anton van Straaten: The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said “Master, I have heard that objects are a very good thing—is this true?” Qc Na looked pityingly at his student and replied, “Foolish read more..

  • Page - 60

    read more..

  • Page - 61

    CHAPTER 3 Objects With the combination of prototypal inheritance, dynamic object extension, and clo‐ sures, JavaScript has one of the most flexible and expressive object systems available in any popular programing language. In JavaScript, all types of functions, arrays, key/value pairs, and data structures in general are really objects. Even primitive types get the object treatment when read more..

  • Page - 62

    As you continue through this chapter, you’ll see that much of the overhead associated with several other GoF design patterns melts away when you understand how to take advantage of JavaScript’s native object capabilities. You may be aware that JavaScript is not a classical OO language. It’s a prototypal lan‐ guage. However, most JavaScript training materials ignore read more..

  • Page - 63

    reused virtually any way you see fit. Once you get the hang of it, composition affords a tremendous amount of freedom compared to classical inheritance. For people who have been immersed in classical inheritance for years and learn how to take real advantage of composition (specifically using prototypal techniques), it is like walking out of a dark tunnel into the light and read more..

  • Page - 64

    haphazard collection of similar objects with unexpectedly divergent properties. Around this time, people start throwing around the word “rewrite” as if it ’s an easier undertaking than refactoring the current mess. Many of the patterns in the GoF book were designed specifically to address these well- known problems. In many ways, the book itself can be read as a critique of read more..

  • Page - 65

    Fluent-Style JavaScript I have not invented a “new style,” composite, modified, or otherwise that is set within distinct form as apart from “this” method or “ that” method. On the contrary, I hope to free my followers from clinging to styles, patterns, or molds. ...The extraordinary part of it lies in its simplicity. —Bruce Lee Programmers with a background in other read more..

  • Page - 66

    simpler, native alternatives. You can learn a lot about JavaScript by reading the code of experienced JavaScript natives who have not been influenced by classical inheritance. Most languages have many different accents and grammars. In fact, almost all disciplines spin off into different schools of thought. Martial arts has kickboxing, jui jitsu, boxing, karate, kung fu, and so on. read more..

  • Page - 67

    Fluent APIs (not to be confused with fluent-style JavaScript) A fluent API is an interface that reads a bit like natural language. Fluent APIs are usually chainable but don’t need to be chained to be fluent. The defining charac‐ teristic is that each method returns an object that has additional methods on it that make sense as a next step. In this way, methods can read more..

  • Page - 68

    if (arguments.length > 1) { throw new Error('Object.create implementation' + ' only accepts the first parameter.'); } function F() {} F.prototype = o; return new F(); }; } When you invoke a constructor with the new keyword, the object referenced by the constructor’s prototype read more..

  • Page - 69

    It’s important to note though that if you mutate an object or array property on the prototype, that mutation will be shared on the prototype. If you replace the whole property, the change is reflected only on that instance: var switchProto = { isOn: function isOn() { return this .state; }, toggle: function toggle() { read more..

  • Page - 70

    Prototype Cloning Sometimes you don’t want to share data on a prototype property. Instead, you want each instance to have its own unique copy of the prototype’s properties. Popular JavaScript libraries have been shipping with a suitable method for cloning prototypes for several years. The cloning method is usually called .extend() . You pass in an object to extend, followed read more..

  • Page - 71

    ok(!switch2.isShared, 'Methods are copied for each instance, not shared.' ); ok(switch1.toggle().isOn(), '.toggle() works.' ); ok(!switch2.isOn(), 'instance safe.' ); switch2.meta.name = 'Breaker switch'; equal(switch1.meta.name, 'Breaker switch', 'Object and array mutations read more..

  • Page - 72

    Imagine you’re programming a video game and there is a common enemy that has dozens or hundreds of copies in the game world. Each copy stores the enemy’s base stats, such as strength and speed, along with methods for all of its attacks and defenses. It also stores the enemy’s position in the game world and current health. You can optimize these objects in read more..

  • Page - 73

    MyConstructor.prototype.myMethod = function () { // A method to be shared... }; It’s less common to see the prototype employed for member data, but it’s a perfectly reasonable place to store default values that are commonly reused. Just be mindful that you’ll need to replace member objects and arrays rather than mutate them in place if you want your changes read more..

  • Page - 74

    this .mph = mph || 0; this .gas = function gas(amount) { amount = amount || 10; this .mph += amount; return this ; }; this .brake = function brake(amount) { amount = amount || 10; this .mph = ((this.mph - amount) < 0)? 0 : this .mph - amount; read more..

  • Page - 75

    : this .mph - amount; return this ; } }; test('Object literal notation.', function () { ok(myCar.color, 'Has a color'); equal(myCar.gas().mph, 10, '.accelerate() should add 10mph.' ); equal(myCar.brake(5).mph, 5, '.brake(5) should subtract 5mph.' ); }); Notice that because the object-literal form doesn’t use a read more..

  • Page - 76

    test('Singleton', function () { var singleton = factory(); hero = singleton.get(), hero2 = singleton.get(); hero.sword = 'Katana'; // Since hero2.sword exists, you know it's the same // object. ok(hero2.sword, 'There can be only one.'); }); You can use the same closure technique to add the parking break functionality to read more..

  • Page - 77

    ); equal(myCar.brake(5).mph, 10, '.brake(5) should subtract 5mph.' ); ok(myCar.toggleParkingBrake().isParked(), '.toggleParkingBrake() toggles on.'); ok(!myCar.toggleParkingBrake().isParked(), '.toggleParkingBrake() toggles off.'); }); As with the constructor function, you get data privacy by encapsulating private data inside the closure, so the only way to read more..

  • Page - 78

    ); }); Notice that the factory method itself is now reduced to a one-liner. The arguments list is replaced with an options hash that allows you to specify exactly which values you want to override. If you take advantage of the prototype feature, you can replace as much or as little of the prototype as you want at runtime. Using the same setup code as before: read more..

  • Page - 79

    • Delegate prototype • Instance state • Encapsulation A stamp is a factory function that has public properties that specify a delegate prototype, default instance state, and a function that sets up encapsulation for object instances. Stamps utilize three different types of inheritance to create the new object: • Delegate prototype: delegation/differential inheritance • Instance read more..

  • Page - 80

    equal(testObj.instanceProp, 'instance property', 'state should be reachable.'); ok(testObj.hasOwnProperty('instanceProp'), 'state should be instance safe.'); equal(testObj.hasOwnProperty('privateProp'), false , 'should hide private properties'); equal(testObj.getPrivate(), 'private property', 'should support privileged methods'); }); Notice that the .create() read more..

  • Page - 81

    Object.getPrototypeOf(obj1).delegateMethod = function () { return 'altered'; }; test('Prototype mutation', function () { equal(obj2.delegateMethod(), 'altered', 'Instances share the delegate prototype.'); }); The .state() method uses concatenative inheritance, which creates a copy of each property from the state prototypes to the new object, allowing you read more..

  • Page - 82

    lastName: 'Hendrix' }); test('Init method', function () { equal(jimi.getName(), 'Jimi Hendrix', 'Object should be initialized.'); }); Of course, creating new objects is just scratching the surface of JavaScript’s OO capa‐ bilities. What you’re about to see is not possible with any currently existing popular JavaScript class library. It’s not possible with the read more..

  • Page - 83

    Stampit’s .compose() method allows you to inherit all three types of prototypes from any number of stamps. The preceding example demonstrates inheritance from multiple ancestors, including private data. Classical OO as we know it today has got nothing on this. Each stamp has a special property called fixed , which stores methods , state , and enclose prototypes. When the read more..

  • Page - 84

    read more..

  • Page - 85

    CHAPTER 4 Modules Modules are reusable software components that form the building blocks of applica‐ tions. Modularity satisfies some very important design goals, perhaps the most impor‐ tant of which is simplicity. When you design an application with a lot of interdependencies between different parts, it becomes more difficult to fully understand the impact of your changes across read more..

  • Page - 86

    Principles of Modularity You can think of modules as small, independent applications that are fully functional and fully testable in their own right. Keep them as small and simple as possible to do the job that they are designed to do. Modules should be: Specialized Each module should have a very specific function. The module’s parts should be integral to solving the single read more..

  • Page - 87

    Interfaces Program to an interface, not an implementation. —The Gang of Four, Design Patterns Interfaces are one of the primary tools of modular software design. Interfaces define a contract that an implementing module will fulfill. For instance, a common problem in JavaScript applications is that the application stops functioning if the Internet connec‐ tion is lost. In order to read more..

  • Page - 88

    In JavaScript, there is no distinction between a class, interface, or object instance. There are only object instances, and that simplification is a good thing. You may be wondering, if there’s no native support for interfaces in JavaScript, why bother to write one at all? When you need multiple implementations of the same interface, it’s good to have a canonical read more..

  • Page - 89

    return this ; }, set: function set(name, value) { this .data[name] = value; return this ; } }) .state({ data: { message: '', published: false read more..

  • Page - 90

    The important part here is the storage interface. First you create the factory (using Stampit in this case, but it can be any function that returns an object that demonstrates the interface). This example has only one method, .save() : storageInterface = stampit().methods({ save: function saveStorage() { throw new Error('.save() method read more..

  • Page - 91

    You could also define the concrete implementations as prototype objects and then pass the appropriate prototype into Stampit or Object.create() during the final step. I prefer to use stamps because they give you a lot of composability. Erich Gamma, one of the Gang of Four authors who created Design Patterns, shared some interesting thoughts about interfaces in an interview with read more..

  • Page - 92

    Here, that variable is called exports , for compatibility with CommonJS (see “Node- Style Modules” on page 82 for an explanation of CommonJS). If exports does not exist, you can fall back on window : (function (exports) { var api = { moduleExists: function test() { return true ; } }; read more..

  • Page - 93

    An upside to this version of the module pattern is that the code you write with it can be easily run and tested in Node. From this point on, when the module pattern gets men‐ tioned, this is the version that should spring to mind. Its ancestor is obsolete. Asynchronous Module Definition On the client side, there is often a need to load modules asynchronously at read more..

  • Page - 94

    } }; return api; }); To kick it off, call require() . You specify dependencies similar to define() : require(['ch04-amd'], function (amd) { var results = amd.testResults(); test('AMD with Require.js', function () { equal(results.test1, true , 'First dependency loaded correctly.'); read more..

  • Page - 95

    Plug-Ins Loader plug-ins are an AMD mechanism that allow you to load non-JavaScript resour‐ ces, such as templates and CSS. Require.js supplies a text! plug-in that you can use to load your HTML templates. To use a plug-in, simply prefix the file path with the plug- in name: 'use strict'; require(['ch04/mymodule.js', 'text!ch04/mymodule.html'], function (myModule, view) read more..

  • Page - 96

    type: 'text/css', rel: 'stylesheet', href: url, }).appendTo('head'); } This obviously isn’t an ideal solution, but as of this writing, there is no standard rec‐ ommended css! plug-in for Require.js. There is a css! plug-in for Curl.js, and you might want to try Xstyle. Use them the same way you define the HTML template. AMD has a read more..

  • Page - 97

    blocked while the required module is being resolved, so it’s safe to start using the module immediately after you require it. First, assign to keys on the free variable exports to declare your module’s public API: 'use strict'; var foo = function foo () { return true ; }; exports.foo = foo; Then use require() to import your module and assign it read more..

  • Page - 98

    npm Node package manager (npm) is a package manager that comes bundled with Node. Contrary to popular belief, npm is not an acronym, according to the npm FAQ, so it’s technically incorrect to capitalize the letters. It provides an easy way to install modules for your application, including all required dependencies. Node relies on the pack‐ age.json specification for read more..

  • Page - 99

    If you want to build a Node app, one of the first things you’ll need to do is create a server. One of the easiest ways to do that is to use Express, a minimal application framework for Node. Before you begin, you should look at the latest version available. By the time you read this, the version you see here should no longer be the latest: $ npm info read more..

  • Page - 100

    ├── range-parser@0.0.4 ├── cookie@0.0.4 ├── crc@0.2.0 ├── commander@0.6.1 ├── debug@0.7.0 ├── mkdirp@0.3.3 ├── send@0.1.0 (mime@1.2.6) └── connect@2.5.0 (pause@0.0.1, bytes@0.1.0, send@0.0.4, formidable@1.0.11, qs@0.5.1) When you run npm install , it will look at package.json and install all of the depen‐ dencies for you, including those that were declared by the read more..

  • Page - 101

    }; export default foo; // No braces required Now you can use the simplified import: import foo from 'es6-foo'; // No braces required If you are interested in experimenting with ES6 modules today, you can use them with the Browserify transform, es6ify. Building Client-Side Code with CommonJS, npm, Grunt, and Browserify There are a variety of competing standards for module read more..

  • Page - 102

    guestSelector = '.guest'; test('Guestlist', function () { ok($list.length, 'List element should have guests.'); }); test('Guests', function () { // Grab the first guest from the list var $guest = $($list.find(guestSelector)[0]), guestExists = !!$guest[0]; // Simulate click $guest.click(); ok($guest.hasClass(checkedinClass), read more..

  • Page - 103

    </body> </html> These tests will obviously fail at first. That’s a good thing. If you can see your tests fail before you make them pass, you eliminate the possibility that your test results are showing you false positives. For this reason, TDD (test-driven development) propo‐ nents advocate writing your unit tests before you implement the code that read more..

  • Page - 104

    Figure 4-3. Failing QUnit screenshot Feature Implementation Failing tests will be listed in red. To make the tests turn green, you’ll need to implement the features. Normally, it’s wise to break the code up into separate concerns. There’s a lot more on that topic in Chapter 5. In this case, you’ll separate presentation concerns from data management. The data will come read more..

  • Page - 105

    The code to manipulate the list DOM elements will go into a file named guestlist‐ view.js, as shown in Example 4-5. Example 4-5. guestlist/src/guestlistview.js var $ = require('jquery-browserify'), checkedinClass = 'icon-check', listClass = 'dropdown-menu', guestClass = 'guest', toggleCheckedIn = function toggleCheckedIn(e) { read more..

  • Page - 106

    By delegating to the parent-ordered list element, you can replace, remove, and add children to the list without worrying about remov‐ ing and replacing event listeners. There won’t be any memory leaks, and you don’t have to wait until the whole list is rendered before you attach the listener. If you’re read more..

  • Page - 107

    The .append() line at the end of the init() function calls jQuery’s .empty() method first for a couple of important reasons. First, if there’s anything in that space already, it should be replaced, but it also releases references to event listeners so that the memory can be garbage collected. This is a read more..

  • Page - 108

    Since you’ll be deploying this app, you should consider all of the code it uses to be part of the app, including its dependencies. You don’t want those dependency versions shift‐ ing around under your feet during your deploy step. The less uncertainty and moving parts you have in a deploy step the better. For that reason, you’re going to want to check in your read more..

  • Page - 109

    // JSHint configuration options. jshint: { browser: false , node: true , strict: false , curly: true , eqeqeq: true , immed: true , latedef: true , newcap: true , nonew: true , noarg: true , sub: true read more..

  • Page - 110

    The Grunt configuration file is just a Node JavaScript module, so you can write functions in it, evaluate expressions, and so on. Browserify requires a little extra configuration sometimes. Please refer to the grunt- browserify documentation for specific settings. Just don’t forget to load the grunt tasks with grunt.loadNpmTasks('grunt-browserify') . The .registerTask() calls make read more..

  • Page - 111

    In general, CSS is a little outside the scope of this book, but there are a few tips you should be aware of. For some great ideas on how to use CSS for applications, see “Scalable and Modular Architecture for CSS” by Jonathan Snook. The Guestlist code employs a custom icon font for the checkbox. Fonts provide a major advantage over traditional methods like png read more..

  • Page - 112

    Conclusion By now you should be familiar with the concept of modularity and comfortable with the idea of using build tools to bundle your application for deployment. You’ve seen an example of how to do that with Browserify. You should be able to figure out how to accomplish the same thing with AMD, if that’s your preference. You saw some hinting at separation of read more..

  • Page - 113

    CHAPTER 5 Separation of Concerns Separation of concerns is the idea that each module or layer in an application should only be responsible for one thing and should not contain code that deals with other things. Separating concerns reduces code complexity by breaking a large application down into many smaller units of encapsulated functionality. It’s easy to confuse separation read more..

  • Page - 114

    Layers are logical groupings of functionality. For example, a data layer might encapsulate functionality related to data and state, while a presentation layer handles display con‐ cerns, such as rendering to the DOM and binding UI behaviors. Tiers are the runtime environments that layers get deployed to. A runtime environment usually consists of at least one physical computer, read more..

  • Page - 115

    programming languages, like aspects (aspect-oriented programming), to DOM widgets, such as a calendar. Dojo is interesting because it started out more monolithic, and now it’s actually a tiny module loader with a large library of components that you can use if you wish, without loading the entire Dojo framework. Larger frameworks tend to be more heavy-handed (opinionated) about read more..

  • Page - 116

    that application modules can stay lightweight and focus exclusively on the service that they provide. Module management typically supplies your application with: • Namespacing • Sandbox (a base layer of functionality that other modules can safely use) • Access to environment variables and bootstrapped data • Module lifecycle hooks (help with setup and teardown) • An event system read more..

  • Page - 117

    usually has to come from server-side configuration, such as environment domain names, application IDs for third-party services, CDN URLs, etc. There are a couple of ways you could source the environment from the server side: load it with Ajax or include it in the HTML with an inline script. The pageData object is intended to register bootstrapped data with the app at read more..

  • Page - 118

    hello: hello }; module.exports = api; This contrived example should really be simplified even further. Since it doesn’t actually use tinyapp , it doesn’t need to require it, and since it’s only exporting a single function (which is actually a pretty good idea for lots of modules), it could just read more..

  • Page - 119

    render: render }); The render() callback is called after: • Any promise returned by load() is resolved. For example, if you return a jQuery Ajax promise from your load() function, it will wait until the Ajax fetch is complete. All jQuery Ajax calls return compatible promises. • All beforeRender callbacks have fired (see “Getting started” on page 102). • The read more..

  • Page - 120

    Try not to do anything blocking in your load() function. For ex‐ ample, you might want to fetch the data that you need to complete your page render, but if you’re loading a large collection and you need to iterate over the collection and do some data processing, save the data processing step read more..

  • Page - 121

    myObject.on('my_event', function handle(data) { console.log(data); }); object.trigger('my_event', 'hi'); // logs 'hi' The downside to triggering events only on the object to which the events belong is that every listener must be given a reference to the object. In situations where there are potentially many objects listening, that strategy requires too much boilerplate code to read more..

  • Page - 122

    Event aggregators can be enormously useful. Because neither emitter nor subscriber need know about the other, aggregators enable very loose coupling between modules. Each only needs a reference to the aggregator. In this case, the emitter and the listener only need to know about app.bus and the invite event in order to communicate. Queues and stacks One disadvantage of the read more..

  • Page - 123

    • For reliable communication between independently scalable and deployable ap‐ plication tiers, a message queue may be the right solution. This guide has really only skimmed the surface of possible messaging patterns. I’ve intentionally focused only on the most common patterns that might be handy in almost every app that grows beyond a few thousand lines of code. For more read more..

  • Page - 124

    app.on('toggled-checkedin', sourceId, toggleCheckedIn.bind(this)); // Relay the change event so the view can listen for it // without knowing anything about the model. this .on('change:checkedIn', function (item) { // Send a shallow copy of the list item as the // message payload. Make sure the new read more..

  • Page - 125

    // If there's no sourceId, just pass this through // to the event emitter. if (args.length <= 2) { events.on.apply(events, arguments); } else { // Otherwise, filter out any events that don't match // the expected sourceId. events.on.call(events, type, function (event) { if (event.sourceId === read more..

  • Page - 126

    api = { create: create }; module.exports = api; Similar to how the model relays its own events, the view listens for DOM events and relays them on the app event aggregator so that other modules can listen (such as models or click loggers). Pay special attention to the delegate() and relayClick() functions, as in Example 5-3. Example 5-3. read more..

  • Page - 127

    app.on('changed.checkedIn', function changeHandler(event) { var id = event.id; // Select the right list item by ID. this .$el.find('#' + id) .toggleClass(checkedinClass, event.checkedIn); }.bind(this)); }, render = function render(guestlist) { var $el = this .$el; read more..

  • Page - 128

    Model View Controller/MV* MVC (Model View Controller) is an architecture for managing separation of presen‐ tation logic from business domain logic in applications. Model refers to application state, and methods for manipulating and retrieving state. Usually there is a mechanism to notify observing views when the model state changes. There can be more than one view listening to a read more..

  • Page - 129

    of the “fat models, skinny controllers” approach. They typically supply or consume a collection of related services. Riot.js is a Model View Presenter (MVP) library that represents the polar opposite of Angular. Riot’s model contains only business-domain logic: state and services to ma‐ nipulate that state. The view is strictly HTML and CSS. The templates contain zero read more..

  • Page - 130

    Backbone.Router allows you to update the location bar when the user selects different views, or create actions that get triggered in response to the user navigating to a given URL. This is the primary responsibility of controllers on the server side, because URLs are generally the only way for the user to communicate with a server-side application. That’s not the case in a read more..

  • Page - 131

    The solid lines represent direct references. Dashed lines represent event listeners. As you can see, with this setup, you don’t need a lot of direct references, which allows your modules to be a lot less coupled. Views listen for state changes and view selection events and emit user-action events. The router listens for user route selections, and emits route- change events. read more..

  • Page - 132

    and delegates events to the view’s root element (this.el) by default. If you omit the selector, the root element will be the target element. Leaving off the selector is probably a code smell. Could you be del‐ egating events to a parent element instead? Event delegation. Event delegation is the process of aggregating events from multiple read more..

  • Page - 133

    You should be aware that you can leak memory if you bind event handlers to each item in a dynamic collection. For example, if you have a collection that utilizes the infinite scroll technique, you’ll need to remove elements from the DOM as they scroll out of view to prevent browser performance issues or crashes. You must remember to remove the event listeners when you read more..

  • Page - 134

    If you implement list items as subviews, you still need to remem‐ ber to call the item’s .remove() method as the item scrolls away, because you still need to stop the view from listening to Backbone events. If you wire up any other kind of event listener (such as an app-level event aggregator), read more..

  • Page - 135

    <script id="guest" type="text/template"> <li class ="<%= guestClass %>" id="<%= id %>" > <span class ="name"><%= name %></span> </li> </script> Unless they are tiny (a few lines), most templates should be in dedi‐ cated files. You may want to group them read more..

  • Page - 136

    guestlist.forEach(function (guestModel) { var guest; // Build the data object to pass into the template. guest = guestModel.toJSON(); // Add the guestClass to the data object. guest.guestClass = guestClass; // Process the template data and append the output to the // list element. read more..

  • Page - 137

    Custom tags are an important aspect of Web Components that allow you to simplify your DOM and write more semantic HTML. For example, if you need to create a knob widget, you can create a component called <x-knob> , which reads a lot better than <div class="knob"> . Custom tags can use prototypal inheritance to inherit the properties of other tags. You can read more..

  • Page - 138

    equal(typeof document.register, 'function', 'Should exist.'); }); test('document.createElement("x-knob")', function () { var knob = document.createElement('x-knob'); ok(knob.getAttribute, 'should produce a custom element.'); }); test('x-knob inheritance', function () { var knob = read more..

  • Page - 139

    Core builds an API on top of Polymer Platform polyfills, providing sugar to make it easier to work with web components. Polymer Elements is a library of reusable custom elements built on top of the Polymer Platform and Polymer Core base layers. As of this writing, Polymer is still in alpha, meaning that it’s in an experimental state, and breaking changes might be read more..

  • Page - 140

    • A developer-friendly package management system with thousands of open-source packages to choose from. Some of these features might take some getting used to if you are accustomed to server- side environments that allow features such as blocking IO and a single thread per con‐ nection (for convenient state management). However, you’ll find that the incredible performance boost read more..

  • Page - 141

    Then initialize your project: $ npm init Express is currently the most popular application framework for Node. It’s easy to learn and use, and it has a vibrant developer community. If you’re going to build applications in Node, chances are you’ll eventually use Express. There’s no time like the present to get started. Install Express: $ npm install --save express read more..

  • Page - 142

    Mout Like Underscore/Lo-Dash, stuff that should probably be included in JavaScript Express Web-application framework Q Promises Qconf Application config Credential Safe password hashing Hogan Mustache for Express Superagent Communicate with APIs Socket.io Realtime communications (WebSocket) Async Asynchronous functional utilities Bunyan Logging Tape Testing Cuid Better than GUID/UUID for web applications Configuration read more..

  • Page - 143

    Use a package like qconf to make the environment variables available in your app. Make sure that the real environment files get added to .gitignore so that you don’t acciden‐ tally check them into your repository. One of the first stumbling blocks you might run into moving from browsers to Node is that you can’t rely on your read more..

  • Page - 144

    app.get('/:name', function (req, res){ var name = req.params.name; res.send('Hello, ' + name); }); A route can be a regular expression: app.get(/(Hugh|Kevin)/, function (req, res, next) { var name = req.params[0], // Whitelisted user output; // Write something to output... res.send('Hello, ' + name); }); Middleware Middleware is software read more..

  • Page - 145

    app.listen(port, function () { console.log('Listening on port ' + port); }); Point a browser at the new server, or just use curl : $ curl http://localhost:44444/ bar Handling errors is just as simple. Again, you’ll use middleware: 'use strict'; var express = require('express'), // Create app instance. app = express(), // Use the `PORT` environment read more..

  • Page - 146

    // Send the user a friendly message: response.send(500, 'Your request was not handled successfully. ' + 'Our smartest fix-it guy has already been alerted. ' + 'Contact us if you need help.'); // Use setTimeout to give the app time to log and clean up, // but shut down ASAP to avoid unintended behavior. // Could also use read more..

  • Page - 147

    Most of the settings for Express are specified with app.set() . You’ll need to use it to configure Express to use the template engine of your choice. There are four options that you should be aware of: // Tell express where to find your templates. app.set('views', __dirname + '/views'); // By default, Express will use a generic HTML wrapper (a layout) // to render all read more..

  • Page - 148

    // .methodOverride() lets you simulate DELETE and PUT // methods with POST methods. Common boilerplate. app.use( express.methodOverride() ); // .static() creates a static file server, which looks for // assets in the /public directory, in this case. app.use( express.static(__dirname + '/public') ); // app.router handles path routing for express apps. app.use( app.router ); // read more..

  • Page - 149

    The next few chapters will cover some concerns that almost every application needs to deal with at some point. For each one, try to keep in mind how the functionality being described can be implemented without intermingling user interface logic with the busi‐ ness domain. Conclusion | 135 read more..

  • Page - 150

    read more..

  • Page - 151

    CHAPTER 6 Access Control Access control models are responsible for granting or restricting access to resources. They depend on two things: user identification (verified by one or more authentication schemes) and feature authorization. Before you grant access to a resource, you need to know that the user is who she claims to be (authentication) and whether or not the user should read more..

  • Page - 152

    other things, uses visitor CPU power to crack stolen password databases that fail to implement the security precautions outlined here. There are botnets that exist today with over 90,000 nodes. Such botnets could crack MD5 password hashes at a rate of nine billion per second. Passwords are vulnerable to the following common attacks: • Rainbow tables • Brute force • Variable read more..

  • Page - 153

    Node.js supplies a suitable random generator called crypto.randomBytes() . It returns a buffer. Wrap it to get a suitable salt string: /** * createSalt(keylength, callback) callback(err, salt) * * Generates a cryptographically secure random string for * use as a password salt using Node's built-in * crypto.randomBytes(). read more..

  • Page - 154

    I discovered 100 hashes in less than 1 ms using a simple MD5 algorithm, and then tried the same thing with Node’s built-in crypto.pbkdf2() function (HMAC-SHA1) set to 80,000 iterations. PBKDF2 took 15.48 seconds. To a user performing a single login attempt per response, the slowdown is barely noticed, but it slows brute force to a crawl. Usage is deceptively simple: read more..

  • Page - 155

    var result = true , length = (x.length > y.length) ? x.length : y.length, i; for (i=0; i<length; i++) { if (x.charCodeAt(i) !== y.charCodeAt(i)) { result = false ; } } return result; read more..

  • Page - 156

    .verify() : var pw = require('credential'), storedHash = '{"hash":...', // truncated to fit on page userInput = 'I have a really great password.'; pw.verify(storedHash, userInput, function (err, isValid) { var msg; if (err) { throw err; } msg = isValid ? read more..

  • Page - 157

    app.listen(3000); Multifactor Authentication Because of the threat of stolen passwords, any policy that relies solely on password protection is unsafe. In order to protect your system from intruders, another line of defense is necessary. Multifactor authentication is an authentication strategy that requires the user to present authentication proof from two or more authentication read more..

  • Page - 158

    var speakeasy = require('speakeasy'); // Returns a key object with ascii, hex, base32, and // QR code representations (the QR code value is a // Google image URL): var key = speakeasy.generate_key({ length: 20, google_auth_qr: true }); // This should match the number on your read more..

  • Page - 159

    navigator.geolocation.getCurrentPosition(function (position) { cb(null, position); }); }; getLocation(function (err, position) { if (err) { return console.log(err); } console.log(position); }); To use the data for geofencing, simply save users’ read more..

  • Page - 160

    For this reason, I can’t recommend WebID for production use today, and neither does the W3C. At the time of this writing, it has not yet evolved into an official working group, and it is probably years from reaching an official recommendation state, if that ever happens. Delegated authentication Delegated authentication allows you to delegate authentication to a specific read more..

  • Page - 161

    // Load the SDK asynchronously (function(d){ var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0]; if (d.getElementById(id)) {return;} js = d.createElement('script'); js.id = id; read more..

  • Page - 162

    Protecting express resources with an authorization strategy is easy: app.put('/posts/:id', authorize(), putPost); The authorize() function returns a middleware function that can check to see whether or not the user has permission to access the requested resource before the route handler has the chance to run. For example, if you want to ensure that the user is logged in, read more..

  • Page - 163

    The user is much more likely to grant permission if you need it to complete an action that she directly requested. This principle holds true whether you’re dealing with Facebook or any other third-party authorization. OAuth 2.0 OAuth 2.0 is an open standard for application authorization that allows clients to access resources on behalf of the resource owner. Essentially, it allows read more..

  • Page - 164

    OAuth 2.0 has been the subject of a lot of security criticism. Security experts cite the large attack surface and the difficulty of correct implementation as reasons to avoid using the specification as-is. However, Facebook and other providers offer bounties for users who are able to uncover security vulnerabilities in their implementations, and those bounties have led to read more..

  • Page - 165

    CHAPTER 7 Logging Logging is a critical piece of application infrastructure, particularly in a modern Java‐ Script application. A typical JavaScript application will involve events in a browser, events on the server, events related to third-party API communication, and a real need for deep profiling and analysis of application performance characteristics. Logging serves every aspect of read more..

  • Page - 166

    • API responses • The sequence of particular events Sometimes it’s useful to know which functions called which at a particular spot in your codebase. It’s possible to log a stack trace with console.trace() : var foo = function foo() { console.trace(); }, bar = function bar() { foo(); }; bar(); read more..

  • Page - 167

    Server Operations Logs are useful for server operations. In case of a failure, it’s often possible to determine which services are affected and which servers might be the source of a problem by examining the logs. It’s usually good idea to collect all of your logs in one data aggregation service so that it’s easy check each critical piece of system infrastructure read more..

  • Page - 168

    Using this technique, it’s possible for investigators to observe the intruder’s behavior in realtime in a safe, sandboxed environment. It’s even possible to simulate full machine clusters with phony data. Sandboxed clusters like this are sometimes established as a preventive measure prior to any known intrusion. The only purpose they serve is to lure intruders, so you know read more..

  • Page - 169

    Viral Factor Word of mouth will make or break your app. If people aren’t sharing it, you won’t achieve organic growth and your app will fail. The standard measure for viral factor is taken from biology’s K-factor, which is designed to measure the infection potential of a virus. In order to measure it, you need to track two variables: i = distribution Number of read more..

  • Page - 170

    • Performance metrics • Server response time • Time to page-ready event • Time to page-rendered event Logging Requests This probably goes without saying, but for most applications, you should log all your server requests, regardless of the outcome. For each request, you may want to log the following: • Timestamp • Hostname of the server (diagnose a clustered server) • read more..

  • Page - 171

    Make sure your request serializer is set up to redact information that could compromise your users’ privacy or your system security. Your request logger should be the among the first items in your middleware stack. Something like Bunyan might come in handy. Bunyan is a lightweight logger that sup‐ ports extensible streams and custom serialization of different types of log read more..

  • Page - 172

    return { message: err.message, name: err.name, stack: getFullStack(err), code: err.code, signal: err.signal, requestId: err.requestId }; } }; To use a serializer, you need to pass an object read more..

  • Page - 173

    // Add the requestId so we can link the // error back to the originating request. err.requestId = req.requestId; log.error({err: err}); next(err); }; }; Most apps will also need a way to log client-side events. For this, you can use a /log.gif endpoint. Counterintuitively, a GET endpoint has read more..

  • Page - 174

    For your convenience, I’ve published all this on npm as bunyan-request-logger . To use it in your app: $ npm install --save bunyan-request-logger There’s a demo client side /log.gif endpoint service included that shows how to use it. You can find it in ./examples/log-only.js. Here’s what it looks like: 'use strict'; var express = require('express'), read more..

  • Page - 175

    // Log request errors: app.use(log.errorLogger); That refers to the following Express error handler: log.errorLogger = function createErrorLogger() { return function errorLogger(err, req, res, next) { // Add the requestId so we can link the // error back to the originating request. read more..

  • Page - 176

    // middleware so that the browser always logs // to the server instead of fetching a useless // OK message from its cache. app.get( '/log.gif', noCache, log.route() ); // Route that triggers a sample error: app.get('/error', function createError(req, res, next) { var err = new Error('Sample error'); err.status read more..

  • Page - 177

    log.info() call will appear as the message, and of course, the timestamp tells you when the event was logged. A successful GET request log entry looks like this: $ curl localhost:3000/log?somedata=yay { "name" :"unnamed app", "hostname" :"unnamed-host", "pid" :62136, "level" :30, read more..

  • Page - 178

    Content-Length: 2 Date: Mon, 07 Oct 2013 07:53:07 GMT Connection: keep-alive", "requestId" :"chmhekaby0000y0ixelvt7y7u", "responseTime" :3 }, "msg" :"", "time" :"2013-10-07T07:53:07.154Z", "v" :0 } read more..

  • Page - 179

    { "name" :"unnamed app", "hostname" :"unnamed-host", "pid" :62136, "level" :50, "err" :{ "message" :"Sample error", "name" :"Error", "requestId" :"chmhekbuq0001y0ix6k6brxq6", read more..

  • Page - 180

    addition to having the alert dispatched to the technicians in charge of repairing the service. Be sure that you’re also logging all your service start-ups so that you can also log when the service becomes available again. Logging Goals Conversion goals can be measured using tools like Google Analytics without explicitly building the log calls into the source code. You should read more..

  • Page - 181

    can deploy and evaluate the solution to determine whether or not it will meet your needs before you scale up and pay full price. New Relic recently developed a Node.js agent, and AppDynamics has acquired Node‐ time in order to provide instrumentation for Node.js applications. You should strongly consider instrumentation tools like these before you deploy your production application. read more..

  • Page - 182

    app.use( log.requestLogger() ); // Route to handle client-side log messages. // // Counter to intuition, client-side logging // works best with GET requests. // // AJAX POST sends headers and body in two steps, // which slows it down. // // This route prepends the cache-control // middleware so that the browser always logs // to the server instead of fetching a useless // No read more..

  • Page - 183

    Conclusion I hope you have a newfound respect for the importance of logging in your application. As you can see, logging can provide a lot of very valuable information. There is a reason that airplanes have lots of dials on their dashboards. As an ASP, your logging is the nervous system that supplies all of the information for those dials. If you’re not delivering read more..

  • Page - 184

    read more..

  • Page - 185

    CHAPTER 8 Building RESTful APIs What is an API? If you’re reading this book, you know that it’s an application program‐ ming interface, but in the context of a RESTful API, we’re specifically talking about an interface that allows users and applications to interact with your application over HTTP using REST architecture (REpresentational State Transfer). For a very basic read more..

  • Page - 186

    So what makes an API beautiful? Beautiful APIs are: Usable Deliver useful services without confusing users. Self-describing Don’t make your API users read the manual; embed the manual in the API. Efficient Bandwidth is expensive. Don’t send more data than the user needs. Responsive Make your API respond as quickly as it can. As you can see, a beautiful API satisfies all of read more..

  • Page - 187

    confusing. Don’t overwhelm API users with gigantic records when they may be looking for a small, specific subset. For example, consider an API that delivers information about music albums: { "id": "chmzq50np0002gfixtr1qp64o", "name": "Settle", "artist": { "id": "chmzq4l480001gfixe8a3nzhm", read more..

  • Page - 188

    Instead of inlining a bunch of completely unrelated data about the artist, you get the artist name (which you’ll likely need to display in any album listing) and an ID you can use to query more information about the artist if it’s needed. The listing now is focused on the particular resource that’s being queried right now: the album. Focus may be the most important read more..

  • Page - 189

    APIs. The most obvious example is the web browser. It doesn’t know anything about a website until you browse to it and start to explore the hyperlinks contained in the re‐ quested document. An example of a generic JSON hypermedia browsing client is Jsonary. That consistency is useful for more than usability. It’s also great for application main‐ tainability, because read more..

  • Page - 190

    Another comment about methods: If your server supports any methods for a given resource, it should deliver a 405 Method Not Allowed error as opposed to a 404 Not Found error for all the other methods. If your API and your documentation says that an endpoint is there, but the user gets a 404 Not Found error, that’s confusing. Luckily, Express makes this easy: read more..

  • Page - 191

    app.use( express.json() ); app.use( express.urlencoded() ); app.use( express.methodOverride() ); app.use( log.requestLogger() ); // Respond to get requests on /albums app.get('/albums', function (req, res) { res.send({ chmzq50np0002gfixtr1qp64o: { "id": "chmzq50np0002gfixtr1qp64o", read more..

  • Page - 192

    Resourceful routing Imagine we’re talking about the process of adding new album cover art to an albums collection, and the UI exposes a way for you to select an album cover via HTTP. The server goes and fetches the image from the URL, encodes it, and adds the resized/ encoded image to the album record. Instead of exposing an /encode-image endpoint, you could PUT to read more..

  • Page - 193

    shopping cart order, and POST again, it will trigger two different checkouts. That’s prob‐ ably not what the user wants. That’s why you’ll see warning messages if you POST some‐ thing and then hit the back button. Browsers will warn that the data will be posted again. If you’re building the server implementation, it’s your job to enforce idempotency for PUT read more..

  • Page - 194

    "artist": "Disclosure" } } } Support POST : // POST /albums -> create, return URI app.post('/albums', function (req, res) { var id = cuid(), album = mixIn({}, req.body, { id: id }); albums[id] = album; res.send(201, { href: '/albums/' + id read more..

  • Page - 195

    album.id = id; albums[id] = album; if (exists) { return res.send(204); } res.send(201, { href: '/albums/' + album.id }); }); Your users need a way to delete albums: // DELETE /albums/:id -> destroy app.delete('/albums/:id', function (req, res, next) { var id = req.params.id, body read more..

  • Page - 196

    It’s RESTish and resourceful, but there’s one more important step you need to take to satisfy those goals: it needs to be self-describing. Self-Describing: Hypermedia Hypertext is a text-based resource with embedded references to other text resources. Hypermedia applies the concept to rich media resources, such as images, video, and audio. The Web started out as a system built read more..

  • Page - 197

    [LI] Idempotent updates Update that will not cause state changes if repeated (aka, safe updates; for ex‐ ample, PUT ) 2. Control data support: [CR] Modify control data for read requests For example, HTTP Accept-* headers [CU] Modify control data for update requests For example, HTTP Content-* headers [CM] Modify control data for interface methods For example, select between read more..

  • Page - 198

    • Your API is more browsable and self-documenting. • You can upgrade or make changes to your API at any time without breaking clients, and all clients will receive the changes automatically. • Reduce long-term maintenance costs. The more clients assume about your API, the more logic you’ll need to support changes you make to the API. • Clients are more adaptable to read more..

  • Page - 199

    HTML as an API Media Type Recently, more adventurous API designers have been experimenting with using HTML instead of JSON-based media types to communicate with their APIs. The thinking is that HTML powers the biggest success case of the REST architectural style and already supports many features that are missing from many other hypermedia types, including the ability to include read more..

  • Page - 200

    ul.properties li.property label Customer ID span.customerId pj123 li.property label Name span.name Peter Joseph ul.actions li.action // read more..

  • Page - 201

    <li class="entity album"> <a href="/albums/a65x0qxr" rel="item"> <ul class="properties"> <li class="property name" > Dark Side of the Moon</li> <li read more..

  • Page - 202

    You’ll need a media type that includes information that allows your client to handle such requests. Imagine that your client is built to handle all requests via Ajax. It intercepts them all, grabs the method parameter, and passes it through to the server without ex‐ amining it (trusting the server to validate it). Now, any method supported by the server will be read more..

  • Page - 203

    module or standalone module for the browser if you don’t want to use Browserify for module management in the client. Using it in the browser is simple: jade.render('a.album(href="/albums/123") Pretty Hate Machine' ); which creates the string: <a href="/albums/123" class="album">Pretty Hate Machine</a> Now you can add that to a documentFragment and read more..

  • Page - 204

    Sort Different applications will have different requirements for sorting complexity, but most should support basic sorting: # Sort albums by year, oldest to newest GET /albums?sort=year+asc # Sort albums by artist, alphabetical GET /albums?sort=artist+asc # Sort albums by year, newest to oldest, then album name, alphabetical GET /albums?sort=year+desc,name+asc Paging read more..

  • Page - 205

    Optimizing for Speed You can have the best API design in the world, but if it’s too slow, nobody will want to use it. Here are some quick tips to keep things moving quickly: • Store all commonly viewed resources and queries in an in-memory cache. Consider Redis or Memcached • Make sure your cache headers and ETags are set properly for all cacheable resources. • read more..

  • Page - 206

    Conclusion This chapter could have been a whole book on its own. I could not possibly tell you everything you need to know about building an API to prepare you for large-scale production within the scope of this book, but hopefully you have been introduced to most of the key concepts, and you at least know which keywords to Google for if you want to learn more. Here read more..

  • Page - 207

    CHAPTER 9 Feature Toggle Continuous deployment is the process of testing, integrating, and deploying software in rapid cycles in order to deliver bug fixes and new features to customers as quickly as possible. It gained popular acceptance as a cornerstone of extreme programming and agile development and is very popular among Software as a Service providers. A feature toggle read more..

  • Page - 208

    the project manager, but it’s easy to go overboard with features. My recommendation is to toggle at the page/route level whenever possible. Features should be toggled on and off at the largest scale possible. For example, if you’re building a new page, you shouldn’t check whether the feature is on for every operation used to build up the page. Instead, toggle the read more..

  • Page - 209

    Lifespan of a Feature The creation of a feature begins with naming and documentation. Before you write a line of code, name and describe the feature, along with any required criteria to qualify it for production activation. “User ratings” might be a good feature name. Development Start with a few unit tests. What does the feature do? How can you verify that behavior with read more..

  • Page - 210

    rollout, and be prepared to roll back feature toggles that have an adverse effect on critical metrics. It’s possible that simple star ratings could improve metrics, but comments could add clutter and distraction. Rolling features out gradually allows you to assess the impact on the overall user experience without taking a big loss if something doesn’t work out as expected. read more..

  • Page - 211

    } </style> </head> <body> <p> Add <code> ?ft=new-feature</code> to the end of the url to see the new feature.</p> <div class="menu"> <ul> <li class="old-feature">Boring old feature </li> read more..

  • Page - 212

    * Get a list of feature names from the url * parameters. * @return {Array} Features list */ getParamFeatures = function getParamFeatures() { var features = getParams().ft; return features ? features.split(',') : undefined ; }, /** * Combine the list of read more..

  • Page - 213

    activeFeatures = getActiveFeatures(baseFeatures, paramFeatures), methods = { /** * Check to see if a feature is active. * @param {String} feature * @return {Boolean} */ read more..

  • Page - 214

    this .emit('deactivated', features); return this ; } }, // Creates the feature toggle object by // composing these methods with an // event emitter using the Stampit // prototypal inheritance library. read more..

  • Page - 215

    Gradual feature rollout allows you to gauge the impact of a change and roll back changes with a minimal impact on user experience and productivity. As you’ve seen, it’s not hard to integrate feature toggles into your code, and it offers a great deal of value. It’s no wonder that feature toggles have been adopted by so many industry-leading software teams. Conclusion | read more..

  • Page - 216

    read more..

  • Page - 217

    CHAPTER 10 Internationalization When you build a web application that grows to or near the saturation point in one country or culture, the easiest way to grow your user base is to expand to other cultures. Internationalization or localization is the process of converting text strings, numbers, dates, and currency into localized languages and representations. One of the biggest hurdles read more..

  • Page - 218

    Once you’ve chosen a solution, getting your translation data where it needs to be is your next challenge. It doesn’t make sense to ship the whole catalog of translation data to the client if they only need a single locale set. If you render all your templates on the client side, you can inject a default set of trans‐ lations into the page data at page-load read more..

  • Page - 219

    To translate some text: // Set the locale Globalize.locale('pt_BR'); // Select the text you want to translate. // Organized by path: Globalize.translate('greetings/bye'); Conclusion I hope you’re thinking of how you can incorporate translations into whatever app you’re currently working on. Remember, it’s really hard to add translation capabilities to your app after read more..

  • Page - 220

    read more..

  • Page - 221

    APPENDIX A JavaScript Style Guide You don’t need to know the arcane inner workings of JavaScript in order to do lots of useful things with it. However, if you plan to write an application with tens of thousands of lines of code, you’re going to need to explore a little deeper. Here you’ll explore some fundamentals that will help you build large applications that are read more..

  • Page - 222

    return true ; } else { return false ; } }, lowPass = function lowPass(number, cutoff) { if (number >= cutoff) { return true ; } else { return false ; } }; module('Filter Examples'); test('highPass', function () { ok(!highPass(2, 5), read more..

  • Page - 223

    The test() function lets you name and define individual module tests. All assertions go inside tests: test( 'Name', function () { // Your assertions here... }); You can test the truthiness of an expression with ok(): ok( true, 'Description'); The first parameter can be any expression you wish to evaluate. If the expression is truthy, the assertion will pass. You can do read more..

  • Page - 224

    More importantly, using an automated tool like JSLint is the best way to enforce a min‐ imum level of code quality and style throughout the code base. In my experience, getting all the developers on the same page is worth a little sacrifice in style. If you can make the trade-offs, what you gain in increased productivity is extraordinary. However, if you can’t make read more..

  • Page - 225

    Use Semicolons There is a recent and growing movement in JavaScript circles to use a style that leaves off optional semicolons. When the JavaScript runtime encounters a condition where there should be a semicolon to make sense of the code but can’t find one, it inserts a semicolon automatically. This behavior is called automatic semicolon insertion (ASI). The new style depends read more..

  • Page - 226

    }()); }); Bracket Placement: Right Side Due to automatic semicolon insertion, brackets should always be placed to the right, on the line that begins the statement in the first getLocation() . Wrong: var getLocation = function getLocation() { return { x: 20, y: 20 }; }; Right: var getLocation = function getLocation() { return read more..

  • Page - 227

    Modules are the best way to avoid name collisions in JavaScript. See Chapter 4. The preceding code is an example of the module pattern described in the modules chapter, but there are several other types of modules, including AMD and Node-style modules. Always Use var If you forget to use the var keyword, your variable assignments will pollute the global scope. Wrong: x is read more..

  • Page - 228

    /* do some stuff with x and y */ var z = true ; /* do some stuff with z */ }()); Right: one var per function: (function myScript() { var x = true , y = true , z = true ; /* do some stuff with x, y, and z */ }()); Avoid Constant Abuse Constants are a class of types that allow you to specify names for values read more..

  • Page - 229

    width: WIDTH, height: HEIGHT }; }, createMenuBox = function createMenuBox() { var WIDTH = '200px', HEIGHT = '400px'; return { width: WIDTH, height: HEIGHT }; }; test('Avoid Constants', function () { var userBox = createUserBox(), read more..

  • Page - 230

    'menuBox should be 200px wide.'); }); Use Functional Iterators When Possible JavaScript offers the capability to program in a functional style, meaning that you can pass functions as arguments to other functions and apply the passed in function to each element in a data resource (array or object). The technique is handy because it can make your code more readable, read more..

  • Page - 231

    'getCount() should count to three.' ); }); Note that you don’t need to worry about the i or length variables in this version. Even better: use the right utility for the job, and you can eliminate even more variables and avoid mutating variables outside the lambda: var getCount = function getCount() { var count = [1, 2, 3]; return read more..

  • Page - 232

    Be Careful with if Statements The results of type coercion in JavaScript can be difficult to predict, even when you know the rules. Here you’ll see how subtle differences in comparisons can lead to sig‐ nificant changes in the results. Be careful when relying on truthiness for logic. Whenever possible, use comparison operators to clarify your meaning. Falsy values include: • read more..

  • Page - 233

    function truthy(x) { if (x) { return true ; } else { return false ; } } test('Truthy', function () { // Falsy equal(truthy(0), true , 'truthy(0)'); // Fail equal(truthy(''), true , "truthy('')"); // Fail equal(truthy(null), true , 'truthy(null)'); // Fail equal(truthy(undefined), true , read more..

  • Page - 234

    equal(exists(''), true , "exists('')"); // Pass equal(exists(null), true , 'exists(null)'); equal(exists(undefined), true , 'exists(undefined)'); equal(exists(false), true , 'exists(false)'); // Pass // Truthy equal(exists('0'), true , "exists('0')"); // Pass equal(exists(new Boolean(false)), true , 'exists(new Boolean(false))'); // Pass read more..

  • Page - 235

    equal(isFalse(['1']), true , "isFalse(['1'])"); // Fail }); The following code will only return true if x is actually set to false : var isFalse = function isFalse(x) { return (x === false ); }; The following function is dangerous, because it will return true for 1 , [1] , and ['1'] : var isTrue = function isTrue(x) { return (x read more..

  • Page - 236

    Right: no side effects: var x = 0; function increment(x) { x += 1; return x; } test('increment() without side effects.', function () { var val = increment(x); equal(val, 1, 'increment() adds one.'); equal(x, 0, 'x is unchanged.'); }); Wherever possible, you should avoid mutating objects declared outside your function. This read more..

  • Page - 237

    // Underscore .extend(), or similar... var instance = extend({}, obj); return instance; } test('setValue() without side effects', function () { var myObj = setValue(obj, 3); equal(myObj.value, 3, 'setValue() should return new value.'); equal(obj.value, 2, 'The original is should be unchanged!'); // Passes }); Don’t Use switch read more..

  • Page - 238

    break ; default : throw new Error('Invalid action.'); break ; } } The method lookup version looks like this: function doAction(action) { var actions = { 'hack': function () { return 'hack'; }, 'slash': function () { return 'slash'; }, 'run': read more..

  • Page - 239

    break ; case ']': case '}': handleClose(token); break ; default : throw new Error('Invalid token.'); break ; } } The method lookup version looks like this: var tokenActions = { '{': handleOpen, '[': handleOpen, ']': handleClose, '}': handleClose }; read more..

  • Page - 240

    object-oriented code. It’s far too common to find implementations of switch ... case , which violate the principles of high cohesion and separation of concerns. I was once a fan of switch ... case as a better alternative to if ... else , but after becoming more familiar with JavaScript, I naturally fell into using method lookup in‐ stead. I haven’t used switch read more..

  • Page - 241

    Most of what eval() can do for you can be done with code that is faster and easier to read. Using eval() forces the JavaScript engine to delay compilation of the eval() code, bypassing the usual code compilation flow and hindering compiler optimizations. eval() can also poke holes in your security and allow cross-site scripting (XSS) attacks. Some good alternatives to read more..

  • Page - 242

    read more..

  • Page - 243

    We’d like to hear your suggestions for improving our indexes. Send email to index@oreilly.com. Index Symbols () (parentheses), 20 A acceptance criteria, 87 access control about, 137 authentication, 137–147 authorization, 147–150 recommendations, 150 access control lists (ACLs), 147 ACLs (access control lists), 147 ad-hoc polymorphism, 32 .addEventListener() method, 22 .addTo() function, 17 affordances read more..

  • Page - 244

    AMD support, 79–82 callback functions, 41 promises and deferreds, 42–44 stateless functions and, 39 asyncTest() function, 27 Atwood’s Law, 2 audit trails, logging, 154 Aura module management, 102 authentication about, 137 Credential library, 141–142 delegated, 146–147 federated, 145–146 multifactor, 143–145 passwords and, 137–141 authorization about, 147 applications and, 148 OAuth 2.0 read more..

  • Page - 245

    partial application and, 40 CLTV (Customer Lifetime Value), 154 CMS (Content Management System), 5 Coders at Work (Siebel), 49 collection polymorphism, 32 Common Locale Data Repository (CLDR), 203 CommonJS project about, 78 asynchronous modules and, 79 module implementations, 82 Promises/A design, 42 consistency (design principle) about, 172, 174 common conventions, 174–178 resourceful routing, read more..

  • Page - 246

    eval() function, 14, 226 events about, 106 .bind() method and, 21 callback functions and, 41 choosing event models, 108 event aggregators, 107, 116, 118 event delegation, 118–119 event emitters, 106, 109 by example, 109–112 JavaScript advantages, 3 logging, 159, 167 message queues, 108 specifying event handlers, 117 .every() method, 34 export keyword, 86 Express framework about, 127, 129 read more..

  • Page - 247

    invoking, 20 JavaScript advantages, 3 JSON and, 6 lambdas, 16–18, 52 method design, 27–36 minimizing side effects, 10–12 as objects, 47 polymorphic, 29–32 sorting parameters, 30 G Gamma, Erich, viii, 77 Gang of Four, viii, 48–50, 73 gconf package, 129 generic programming, 32–34 geofencing, 144 Geolocation API (HTML), 144 GET verb (HTTP), 7, 159, 163, 175, 178 Globalize plug-in read more..

  • Page - 248

    fluent style JavaScript and, 53 Globalize plug-in, 203 IIFE, 18 microlibraries and, 101 .on() method, 91, 117, 118 promises, 42–44 JSLint, 210 JSON (JavaScript Object Notation) about, 2 data storage and communication, 5–6 Jiron comparison, 188 RESTful web services and, 6–8 Jsonary client, 175 K K-factor (viral factor), 155 Keep it Simple Stupid (KISS), 9 Kestrel message queue, 108 Key read more..

  • Page - 249

    building client-side code, 87–97 design principles, 72 ES6, 86 interfaces and, 73–77 managing, 101–105 module pattern, 77–79 node style, 82–83 npm support, 84–86 separation of concerns, 99 Moment.js library, 203 MongoDB data stores, 6 Monthly Recurring Revenue (MRR), 154 Mozilla Developer Network (MDN), 217 Mozilla Persona, 145 MRR (Monthly Recurring Revenue), 154 multifactor authentication read more..

  • Page - 250

    variable time equality, 140 vulnerability of, 138 performance JavaScript advantages, 2 profiling, 166 Persona (Mozilla), 145 plug-ins (loader), 81–82 Polymer website, 125 polymorphism ad-hoc, 32 collection, 32–34 function, 29–32 parametric, 32 possession factor (authentication), 143 POST verb (HTTP), 7–8, 159, 175, 178 primitive types, 47 private data, encapsulation and, 59, 61–64, 68 privileged read more..

  • Page - 251

    affordances and, 182 HATEOAS acronym and, 183–184 HTML and, 185 Jade template engine, 185–187 Jiron type, 187–189 self-invoked anonymous functions, 18 semantic versioning, 85 semicolons (best practice), 211 separation of concerns about, 99 application presentation, 117–125 best practices, 226 client-side concerns, 100–125 DOM manipulation, 117–125 events, 106–112 module management, 101–105 MVC read more..

  • Page - 252

    event aggregators and, 107 .extend() method, 29, 56 template support, 120–121 Unicode CLDR, 203 Uniform Resource Indicator (URI), 7 universal module definition (UMD), 80 URI (Uniform Resource Indicator), 7 usability (design principle) consistency, 172, 174–182 focus, 172–174 user stories, 87 V van Straaten, Anton, 45 var keyword, 22, 213 Venners, Bill, 77 view (MVC), 114, 117 viral factor read more..

  • Page - 253

    About the Author Eric Elliott is a veteran of JavaScript application development. He has served as com‐ puter scientist for the Adobe Creative Cloud team, JavaScript lead at Tout (social video), head of client-side architecture at Zumba Fitness (the leading global fitness brand), author, public speaker, UX consultant, and viral-application consultant. He lives in the San read more..

Write Your Review