O'Reilly logo

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Node.js Design Patterns

Book Description

Get the best out of Node.js by mastering a series of patterns and techniques to create modular, scalable, and efficient applications

In Detail

Node.js is a massively popular software platform that lets you use JavaScript to easily create scalable server-side applications. It allows you to create efficient code, enabling a more sustainable way of writing software made of only one language across the full stack, along with extreme levels of reusability, pragmatism, simplicity, and collaboration. Node.js is revolutionizing the web and the way people and companies create their software.

In this book, we will take you on a journey across various ideas and components, and the challenges you would commonly encounter while designing and developing software using the Node.js platform. You will also discover the "Node.js way" of dealing with design and coding decisions.

The book kicks off by exploring the fundamental principles and components that define the platform. It then shows you how to master asynchronous programming and how to design elegant and reusable components using well-known patterns and techniques. The book rounds off by teaching you the various approaches to scale, distribute, and integrate your Node.js application.

What You Will Learn

  • Design and implement a series of server-side JavaScript patterns so you understand why and when to apply them in different use case scenarios
  • Understand the fundamental Node.js components and use them to their full potential
  • Untangle your modules by organizing and connecting them coherently
  • Reuse well-known solutions to circumvent common design and coding issues
  • Deal with asynchronous code with comfort and ease
  • Identify and prevent common problems, programming errors, and anti-patterns

Downloading the example code for this book. You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.

Table of Contents

  1. Node.js Design Patterns
    1. Table of Contents
    2. Node.js Design Patterns
    3. Credits
    4. About the Author
    5. Acknowledgments
    6. About the Reviewers
    7. www.PacktPub.com
      1. Support files, eBooks, discount offers, and more
        1. Why subscribe?
        2. Free access for Packt account holders
    8. Preface
      1. What this book covers
      2. What you need for this book
      3. Who this book is for
      4. Conventions
      5. Reader feedback
      6. Customer support
        1. Downloading the example code
        2. Errata
        3. Piracy
        4. Questions
    9. 1. Node.js Design Fundamentals
      1. The Node.js philosophy
        1. Small core
        2. Small modules
        3. Small surface area
        4. Simplicity and pragmatism
      2. The reactor pattern
        1. I/O is slow
        2. Blocking I/O
        3. Non-blocking I/O
        4. Event demultiplexing
        5. The reactor pattern
        6. The non-blocking I/O engine of Node.js – libuv
        7. The recipe for Node.js
      3. The callback pattern
        1. The continuation-passing style
          1. Synchronous continuation-passing style
          2. Asynchronous continuation-passing style
          3. Non continuation-passing style callbacks
        2. Synchronous or asynchronous?
          1. An unpredictable function
          2. Unleashing Zalgo
          3. Using synchronous APIs
          4. Deferred execution
        3. Node.js callback conventions
          1. Callbacks come last
          2. Error comes first
          3. Propagating errors
          4. Uncaught exceptions
      4. The module system and its patterns
        1. The revealing module pattern
        2. Node.js modules explained
          1. A homemade module loader
          2. Defining a module
          3. Defining globals
          4. module.exports vs exports
          5. require is synchronous
          6. The resolving algorithm
          7. The module cache
          8. Cycles
        3. Module definition patterns
          1. Named exports
          2. Exporting a function
          3. Exporting a constructor
          4. Exporting an instance
          5. Modifying other modules or the global scope
      5. The observer pattern
        1. The EventEmitter
        2. Create and use an EventEmitter
        3. Propagating errors
        4. Make any object observable
        5. Synchronous and asynchronous events
        6. EventEmitter vs Callbacks
        7. Combine callbacks and EventEmitter
      6. Summary
    10. 2. Asynchronous Control Flow Patterns
      1. The difficulties of asynchronous programming
        1. Creating a simple web spider
        2. The callback hell
      2. Using plain JavaScript
        1. Callback discipline
        2. Applying the callback discipline
        3. Sequential execution
          1. Executing a known set of tasks in sequence
          2. Sequential iteration
            1. Web spider version 2
            2. Sequential crawling of links
            3. The pattern
        4. Parallel execution
          1. Web spider version 3
          2. The pattern
          3. Fixing race conditions in the presence of concurrent tasks
        5. Limited parallel execution
          1. Limiting the concurrency
          2. Globally limiting the concurrency
            1. Queues to the rescue
            2. Web spider version 4
      3. The async library
        1. Sequential execution
          1. Sequential execution of a known set of tasks
          2. Sequential iteration
        2. Parallel execution
        3. Limited parallel execution
      4. Promises
        1. What is a promise?
        2. Promises/A+ implementations
        3. Promisifying a Node.js style function
        4. Sequential execution
          1. Sequential iteration
          2. Sequential iteration – the pattern
        5. Parallel execution
        6. Limited parallel execution
      5. Generators
        1. The basics
          1. A simple example
          2. Generators as iterators
          3. Passing values back to a generator
        2. Asynchronous control flow with generators
          1. Generator-based control flow using co
        3. Sequential execution
        4. Parallel execution
        5. Limited parallel execution
          1. Producer-consumer pattern
          2. Limiting the download tasks concurrency
      6. Comparison
      7. Summary
    11. 3. Coding with Streams
      1. Discovering the importance of streams
        1. Buffering vs Streaming
        2. Spatial efficiency
          1. Gzipping using a buffered API
          2. Gzipping using streams
        3. Time efficiency
        4. Composability
      2. Getting started with streams
        1. Anatomy of streams
        2. Readable streams
          1. Reading from a stream
            1. The non-flowing mode
            2. The flowing mode
          2. Implementing Readable streams
        3. Writable streams
          1. Writing to a stream
          2. Back-pressure
          3. Implementing Writable streams
        4. Duplex streams
        5. Transform streams
          1. Implementing Transform streams
        6. Connecting streams using pipes
        7. Useful packages for working with streams
          1. readable-stream
          2. through and from
      3. Asynchronous control flow with streams
        1. Sequential execution
        2. Unordered parallel execution
          1. Implementing an unordered parallel stream
          2. Implementing a URL status monitoring application
        3. Unordered limited parallel execution
          1. Ordered parallel execution
      4. Piping patterns
        1. Combining streams
          1. Implementing a combined stream
        2. Forking streams
          1. Implementing a multiple checksum generator
        3. Merging streams
          1. Creating a tarball from multiple directories
        4. Multiplexing and demultiplexing
          1. Building a remote logger
            1. Client side – Multiplexing
            2. Server side – demultiplexing
            3. Running the mux/demux application
          2. Multiplexing and demultiplexing object streams
      5. Summary
    12. 4. Design Patterns
      1. Factory
        1. A generic interface for creating objects
        2. A mechanism to enforce encapsulation
        3. Building a simple code profiler
        4. In the wild
      2. Proxy
        1. Techniques for implementing proxies
          1. Object composition
          2. Object augmentation
        2. A comparison of the different techniques
        3. Creating a logging Writable stream
        4. Proxy in the ecosystem – function hooks and AOP
        5. In the wild
      3. Decorator
        1. Techniques for implementing decorators
          1. Composition
          2. Object augmentation
        2. Decorating a LevelUP database
          1. Introducing LevelUP and LevelDB
          2. Implementing a LevelUP plugin
        3. In the wild
      4. Adapter
        1. Using LevelUP through the filesystem API
        2. In the wild
      5. Strategy
        1. Multi-format configuration objects
        2. In the wild
      6. State
        1. Implementing a basic fail-safe socket
      7. Template
        1. A configuration manager template
        2. In the wild
      8. Middleware
        1. Middleware in Express
        2. Middleware as a pattern
        3. Creating a middleware framework for ØMQ
          1. The Middleware Manager
          2. A middleware to support JSON messages
          3. Using the ØMQ middleware framework
            1. The server
            2. The client
      9. Command
        1. A flexible pattern
          1. The task pattern
          2. A more complex command
      10. Summary
    13. 5. Wiring Modules
      1. Modules and dependencies
        1. The most common dependency in Node.js
        2. Cohesion and Coupling
        3. Stateful modules
          1. The Singleton pattern in Node.js
      2. Patterns for wiring modules
        1. Hardcoded dependency
          1. Building an authentication server using hardcoded dependencies
            1. The db module
            2. The authService module
            3. The authController module
            4. The app module
            5. Running the authentication server
          2. Pros and cons of hardcoded dependencies
        2. Dependency injection
          1. Refactoring the authentication server to use dependency injection
          2. The different types of dependency injection
          3. Pros and cons of dependency injection
        3. Service locator
          1. Refactoring the authentication server to use a service locator
          2. Pros and cons of a service locator
        4. Dependency injection container
          1. Declaring a set of dependencies to a DI container
          2. Refactoring the authentication server to use a DI container
          3. Pros and cons of a Dependency Injection container
      3. Wiring plugins
        1. Plugins as packages
        2. Extension points
        3. Plugin-controlled vs Application-controlled extension
        4. Implementing a logout plugin
          1. Using hardcoded dependencies
          2. Exposing services using a service locator
          3. Exposing services using dependency injection
          4. Exposing services using a dependency injection container
      4. Summary
    14. 6. Recipes
      1. Requiring asynchronously initialized modules
        1. Canonical solutions
        2. Preinitialization queues
          1. Implementing a module that initializes asynchronously
          2. Wrapping the module with preinitialization queues
        3. In the wild
      2. Asynchronous batching and caching
        1. Implementing a server with no caching or batching
        2. Asynchronous request batching
          1. Batching requests in the total sales web server
        3. Asynchronous request caching
          1. Caching requests in the total sales web server
          2. Notes about implementing caching mechanisms
        4. Batching and caching with Promises
      3. Running CPU-bound tasks
        1. Solving the subset sum problem
        2. Interleaving with setImmediate
          1. Interleaving the steps of the subset sum algorithm
          2. Considerations on the interleaving pattern
        3. Using multiple processes
          1. Delegating the subset sum task to other processes
            1. Implementing a process pool
            2. Communicating with a child process
            3. Communicating with the parent process
          2. Considerations on the multiprocess pattern
      4. Sharing code with the browser
        1. Sharing modules
          1. Universal Module Definition
            1. Creating an UMD module
            2. Considerations on the UMD pattern
          2. Introducing Browserify
            1. Exploring the magic of Browserify
            2. The advantages of using Browserify
        2. Fundamentals of cross-platform development
          1. Runtime code branching
          2. Build-time code branching
          3. Design patterns for cross-platform development
        3. Sharing business logic and data validation using Backbone Models
          1. Implementing the shared models
          2. Implementing the platform-specific code
          3. Using the isomorphic models
          4. Running the application
      5. Summary
    15. 7. Scalability and Architectural Patterns
      1. An introduction to application scaling
        1. Scaling Node.js applications
        2. The three dimensions of scalability
      2. Cloning and load balancing
        1. The cluster module
          1. Notes on the behavior of the cluster module
          2. Building a simple HTTP server
          3. Scaling with the cluster module
          4. Resiliency and availability with the cluster module
          5. Zero-downtime restart
        2. Dealing with stateful communications
          1. Sharing the state across multiple instances
          2. Sticky load balancing
        3. Scaling with a reverse proxy
          1. Load balancing with Nginx
        4. Using a Service Registry
          1. Implementing a dynamic load balancer with http-proxy and seaport
        5. Peer-to-peer load balancing
          1. Implementing an HTTP client that can balance requests across multiple servers
      3. Decomposing complex applications
        1. Monolithic architecture
        2. The Microservice architecture
          1. An example of the Microservice architecture
          2. Pros and cons of microservices
            1. Every service is expendable
            2. Reusability across platforms and languages
            3. A way to scale the application
            4. The challenges of microservices
        3. Integration patterns in a Microservice architecture
          1. The API proxy
          2. API orchestration
          3. Integration with a message broker
      4. Summary
    16. 8. Messaging and Integration Patterns
      1. Fundamentals of a messaging system
        1. One-way and request/reply patterns
        2. Message types
        3. Asynchronous messaging and queues
        4. Peer-to-peer or broker-based messaging
      2. Publish/subscribe pattern
        1. Building a minimalist real-time chat application
          1. Implementing the server side
          2. Implementing the client side
          3. Running and scaling the chat application
        2. Using Redis as a message broker
        3. Peer-to-peer publish/subscribe with ØMQ
          1. Introducing ØMQ
          2. Designing a peer-to-peer architecture for the chat server
          3. Using the ØMQ PUB/SUB sockets
        4. Durable subscribers
          1. Introducing AMQP
          2. Durable subscribers with AMQP and RabbitMQ
            1. Designing a history service for the chat application
            2. Implementing a reliable history service using AMQP
            3. Integrating the chat application with AMQP
      3. Pipelines and task distribution patterns
        1. The ØMQ fan-out/fan-in pattern
          1. PUSH/PULL sockets
          2. Building a distributed hashsum cracker with ØMQ
            1. Implementing the ventilator
            2. Implementing the worker
            3. Implementing the sink
            4. Running the application
        2. Pipelines and competing consumers in AMQP
          1. Point-to-point communications and competing consumers
          2. Implementing the hashsum cracker using AMQP
            1. Implementing the producer
            2. Implementing the worker
            3. Implementing the result collector
            4. Running the application
      4. Request/reply patterns
        1. Correlation identifier
          1. Implementing a request/reply abstraction using correlation identifiers
            1. Abstracting the request
            2. Abstracting the reply
            3. Trying the full request/reply cycle
        2. Return address
          1. Implementing the return address pattern in AMQP
            1. Implementing the request abstraction
            2. Implementing the reply abstraction
            3. Implementing the requestor and the replier
      5. Summary
    17. Index