惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
P
Privacy & Cybersecurity Law Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
C
Cybersecurity and Infrastructure Security Agency CISA
S
Security Affairs
Latest news
Latest news
Security Latest
Security Latest
N
News and Events Feed by Topic
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
The Exploit Database - CXSecurity.com
The Last Watchdog
The Last Watchdog
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
V
Vulnerabilities – Threatpost
Hacker News - Newest:
Hacker News - Newest: "LLM"
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
The Cloudflare Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
博客园_首页
S
Secure Thoughts
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
AWS News Blog
AWS News Blog
腾讯CDC
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Register - Security
The Register - Security
N
News and Events Feed by Topic
A
Arctic Wolf
MongoDB | Blog
MongoDB | Blog
爱范儿
爱范儿
Project Zero
Project Zero
A
About on SuperTechFans
罗磊的独立博客
云风的 BLOG
云风的 BLOG
Know Your Adversary
Know Your Adversary
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
K
Kaspersky official blog
L
LINUX DO - 最新话题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Fortinet All Blogs

Minko Gechev's blog

skillgrade Unit Tests for AI Agent Skills You Should Care About AI Generative Development LLM-first Web Framework Reactive framework in ~200 lines of JavaScript Managing Angular Are LLMs going to replace us? Prefetching Heuristics Design Patterns in Open Source Projects - Part II Design Patterns in Open Source Projects - Part I What I learned doing 125 public talks - Part I Dynamic imports solve all the problems, right? 5 Angular CLI Features You Didn't Know About Angular quicklink Preloading Strategy Introducing Bazel Schematics for Angular CLI Building TypeScript Projects with Bazel Joining Google Playing Mortal Kombat with TensorFlow.js. Transfer learning and data augmentation Fast, extensible, configurable, and beautiful linter for Go Introducing Guess.js - a toolkit for enabling data-driven user-experiences on the Web Machine Learning-Driven Bundling. The Future of JavaScript Tooling. JavaScript Decorators for Declarative and Readable Code 3 Tricks For Using Redux and Immutable.js with TypeScript Follow Your Dream Career with Open Source. Personal Story. Redux Anti-Patterns - Part 1. State Management. Faster Angular Applications - Understanding Differs. Developing a Custom IterableDiffer Faster Angular Applications - Part 2. Pure Pipes, Pure Functions and Memoization Faster Angular Applications - Part 1. On Push Change Detection and Immutability Understanding Dynamic Scoping and TemplateRef Implementing a Simple Compiler on 25 Lines of JavaScript Developing Statically Typed Programming Language WebVR for a Gamified IDE 7 Angular Tools That You Should Consider Announcing ngrev - Reverse Engineering Tool for Angular Implementing Angular's Dependency Injection in React. Understanding Element Injectors. Distributing an Angular Library - The Brief Guide Angular in Production Ahead-of-Time Compilation in Angular 2.5X Smaller Angular 2 Applications with Google Closure Compiler Using Stripe with Angular (Deprecated) Building an Angular Application for Production Implementing the Missing "resolve" Feature of the Angular 2 Router Scalable Single-Page Application Architecture Managing ambient type definitions and dealing with the "Duplicate identifier" TypeScript error Static Code Analysis of Angular 2 and TypeScript Projects Enforcing Best Practices with Static Code Analysis of Angular 2 Projects ViewChildren and ContentChildren in Angular Dynamically Configuring the Angular's Router Angular 2 Hot Loader Lazy Loading of Route Components in Angular 2 Aspect-Oriented Programming in JavaScript Flux in Depth. Store and Network Communication. Using JSX with TypeScript Flux in Depth. Overview and Components. Even Faster AngularJS Data Structures Boost the Performance of an AngularJS Application Using Immutable Data - Part 2 Angular2 - First Impressions Build Your own Simplified AngularJS in 200 Lines of JavaScript Persistent State of ReactJS Component Boost the Performance of an AngularJS Application Using Immutable Data Processing Binary Protocols with Client-Side JavaScript Stream your Desktop to HTML5 Video Element Multi-User Video Conference with WebRTC Asynchronous calls with ES6 generators Binary Tree iterator with ES6 generators WebRTC chat with React.js AngularJS in Patterns (Part 3) Using GitHub Pages with Jekyll! AngularJS in Patterns (Part 1). Overview of AngularJS Singleton in JavaScript Express over HTTPS What I get from the JavaScript MV* frameworks Remote Desktop Client with AngularJS and Yeoman The magic of $resource (or simply a client-side Active Record) AngularJS Inheritance Patterns AngularAOP v0.1.0 Advanced JavaScript at Sofia University AngularJS style guide Lazy prefetching of AngularJS partials VNC client on 200 lines of JavaScript Aspect-Oriented Programming with AngularJS CSS3 flipping effect Practical programming with JavaScript Why I should use publish/subscribe in JavaScript JavaScript, the weird parts Functional programming with JavaScript plainvm Looking for performance? Probably you should NOT use [].sort (V8) JavaScript image scaling ELang Caching CSS with localStorage Self-invoking functions in JavaScript (or Immediately Invoked Function Expressions) Asus N56VZ + Ubuntu 12.04 (en) Asus N56VZ + Ubuntu 12.04 Debian Squeeze + LXDE on Google Nexus S (or having some fun while suffering) HTML5 image editor Курсови проекти – ФМИ Carousel Gallery SofiaJS...
AngularJS in Patterns (Part 2). Services.
2014-06-08 · via Minko Gechev's blog

Edit · Jun 8, 2014 · 11 minutes read · Follow @mgechev AngularJS AngularJS overview Design patterns Development JavaScript Object-Oriented Programming patterns Programming Software engineering web application

This publication aims to provide a more theoretical overview of some of the AngularJS components in order to show you how the things you are already familiar with (like different Object-Oriented Design Patterns) fit in the picture.

Link to the first part of the series.

This blog post continues the series “AngularJS in Patterns”. You can find the original GitHub repository, which contains all the information at github.com/mgechev/angularjs-in-patterns. If you like my work you can follow me at github.com/mgechev.

Services

In this sub-chapter we are going to take a look at the design and architectural patterns used in AngularJS’ services.

Note: Some of the described patterns are used in other components as well but their usage is almost equivalent so they are explained here.

Singleton

The singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects.

In the UML diagram below the singleton design pattern is illustrated.

Singleton

When given dependency is required by any component, AngularJS resolves it using the following algorithm:

  • Takes its name and makes a lookup at a hash map, which is defined into a lexical closure (so it has a private visibility).
  • If the dependency exists AngularJS passes it as parameter to the component, which requires it.
  • If the dependency does not exist:
    • AngularJS instantiates it by calling the factory method of its provider (i.e. $get). Note that instantiating the dependency may require recursive call to the same algorithm, for resolving all the dependencies required by the given dependency. This process may lead to circular dependency.
    • AngularJS caches it inside the hash map mentioned above.
    • AngularJS passes it as parameter to the component, which requires it.

We can take better look at the AngularJS’ source code, which implements the method getService:

function getService(serviceName) {
  if (cache.hasOwnProperty(serviceName)) {
    if (cache[serviceName] === INSTANTIATING) {
      throw $injectorMinErr('cdep', 'Circular dependency found: {0}', path.join(' <- '));
    }
    return cache[serviceName];
  } else {
    try {
      path.unshift(serviceName);
      cache[serviceName] = INSTANTIATING;
      return cache[serviceName] = factory(serviceName);
    } catch (err) {
      if (cache[serviceName] === INSTANTIATING) {
        delete cache[serviceName];
      }
      throw err;
    } finally {
      path.shift();
    }
  }
}

We can think of each service as a singleton, because each service is instantiated no more than a single time. We can consider the cache as a singleton manager. There is a slight variation from the UML diagram illustrated above because instead of keeping static, private reference to the singleton inside its constructor function, we keep the reference inside the singleton manager (stated in the snippet above as cache).

This way the services are actually singletons but not implemented through the Singleton pattern, which provides a few advantages over the standard implementation:

  • It improves the testability of your source code
  • You can control the creation of singleton objects (in our case the IoC container controls it for us, by instantiating the singletons lazy)

For further discussion on this topic Miško Hevery’s article in the Google Testing blog could be considered.

Factory Method

The factory method pattern is a creational pattern, which uses factory methods to deal with the problem of creating objects without specifying the exact class of object that will be created. This is done by creating objects via a factory method, which is either specified in an interface (abstract class) and implemented in implementing classes (concrete classes); or implemented in a base class, which can be overridden when inherited in derived classes; rather than by a constructor.

Factory Method

Lets consider the following snippet:

myModule.config(function ($provide) {
  $provide.provider('foo', function () {
    var baz = 42;
    return {
      //Factory method
      $get: function (bar) {
        var baz = bar.baz();
        return {
          baz: baz
        };
      }
    };
  });
});

In the code above we use the config callback in order to define new “provider”. Provider is an object, which has a method called $get. Since in JavaScript we don’t have interfaces and the language is duck-typed there is a convention to name the factory method of the providers that way.

Each service, filter, directive and controller has a provider (i.e. object which factory method, called $get), which is responsible for creating the component’s instance.

We can dig a little bit deeper in AngularJS’ implementation:

//...

createInternalInjector(instanceCache, function(servicename) {
  var provider = providerInjector.get(servicename + providerSuffix);
  return instanceInjector.invoke(provider.$get, provider, undefined, servicename);
}, strictDi));

//...

function invoke(fn, self, locals, serviceName){
  if (typeof locals === 'string') {
    serviceName = locals;
    locals = null;
  }

  var args = [],
      $inject = annotate(fn, strictDi, serviceName),
      length, i,
      key;

  for(i = 0, length = $inject.length; i < length; i++) {
    key = $inject[i];
    if (typeof key !== 'string') {
      throw $injectorMinErr('itkn',
              'Incorrect injection token! Expected service name as string, got {0}', key);
    }
    args.push(
      locals && locals.hasOwnProperty(key)
      ? locals[key]
      : getService(key)
    );
  }
  if (!fn.$inject) {
    // this means that we must be an array.
    fn = fn[length];
  }

  return fn.apply(self, args);
}

From the example above we can notice how the $get method is actually used:

instanceInjector.invoke(provider.$get, provider, undefined, servicename)

The snippet above calls the invoke method of instanceInjector with the factory method (i.e. $get) of given service, as first argument. Inside invoke’s body annotate is called with first argument the factory method. Annotate resolves all dependencies through the dependency injection mechanism of AngularJS, which was considered above. When all dependencies are resolved the factory method is called: fn.apply(self, args).

If we think in terms of the UML diagram above, we can call the provider a “ConcreteCreator” and the actual component, which is being created a “Product”.

There are a few benefits of using the factory method pattern in this case, because of the indirection it creates. This way the framework can take care of the boilerplates during the instantiation of new components like:

  • The most appropriate moment, when the component needs to be instantiated
  • Resolving all the dependencies required by the component
  • The number of instances the given component is allowed to have (for services and filters only a single one but multiple for the controllers)

Decorator

The decorator pattern (also known as Wrapper, an alternative naming shared with the Adapter pattern) is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class.

Decorator

AngularJS provides out-of-the-box way for extending and/or enchanting the functionality of already existing services. Using the method decorator of $provide you can create “wrapper” of any service you have previously defined or used by a third-party:

myModule.controller('MainCtrl', function (foo) {
  foo.bar();
});

myModule.factory('foo', function () {
  return {
    bar: function () {
      console.log('I\'m bar');
    },
    baz: function () {
      console.log('I\'m baz');
    }
  };
});

myModule.config(function ($provide) {
  $provide.decorator('foo', function ($delegate) {
    var barBackup = $delegate.bar;
    $delegate.bar = function () {
      console.log('Decorated');
      barBackup.apply($delegate, arguments);
    };
    return $delegate;
  });
});

The example above defines new service called foo. In the config callback the method $provide.decorator is called with first argument "foo", which is the name of the service, we want to decorate and second argument factory function, which implements the actual decoration. $delegate keeps reference to the original service foo. Using the dependency injection mechanism of AngularJS, reference to this local dependency is passed as first argument of the constructor function. We decorate the service by overriding its method bar. The actual decoration is simply extending bar by invoking one more console.log statement - console.log('Decorated'); and after that calls the original bar method with the appropriate context.

Using this pattern is especially useful when we need to modify the functionality of third party services. In cases when multiple similar decorations are required (like performance measurement of multiple methods, authorization, logging, etc.), we may have a lot of duplications and violate the DRY principle. In such cases it is useful to use aspect-oriented programming. The only AOP framework for AngularJS I’m aware of could be found at github.com/mgechev/angular-aop.

Facade

A facade is an object that provides a simplified interface to a larger body of code, such as a class library. A facade can:

  1. make a software library easier to use, understand and test, since the facade has convenient methods for common tasks;
  1. make the library more readable, for the same reason;
  1. reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system;
  1. wrap a poorly designed collection of APIs with a single well-designed API (as per task needs).

Facade

There are a few facades in AngularJS. Each time you want to provide higher level API to given functionality you practically create a facade.

For example, lets take a look at how we can create an XMLHttpRequest POST request:

var http = new XMLHttpRequest(),
    url = '/example/new',
    params = encodeURIComponent(data);
http.open("POST", url, true);

http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");

http.onreadystatechange = function () {
  if(http.readyState == 4 && http.status == 200) {
    alert(http.responseText);
  }
}
http.send(params);
But if we want to post this data using the AngularJS’ $http service we can:
$http({
  method: 'POST',
  url: '/example/new',
  data: data
})
.then(function (response) {
  alert(response);
});
or we can even:
$http.post('/someUrl', data)
.then(function (response) {
  alert(response);
});
The second option provides pre-configured version, which creates a HTTP POST request to the given URL.

Even higher level of abstraction is being created by $resource, which is build over the $http service. We will take a further look at this service in Active Record and Proxy sections.

Proxy

A proxy, in its most general form, is a class functioning as an interface to something else. The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.

Proxy

We can distinguish three different types of proxy:

  • Virtual Proxy
  • Remote Proxy
  • Protection Proxy

In this sub-chapter we are going to take a look at AngularJS’ implementation of Virtual Proxy.

In the snippet below, there is a call to the get method of $resource instance, called User:

var User = $resource('/users/:id'),
    user = User.get({ id: 42 });
console.log(user); //{}

console.log would output an empty object. Since the AJAX request, which happens behind the scenes, when User.get is invoked, is asynchronous, we don’t have the actual user when console.log is called. Just after User.get makes the GET request, it returns an empty object and keeps reference to it. We can think of this object as virtual proxy (a simple placeholder), which would be populated with the actual data once the client receives response by the server.

How does this works with AngularJS? Well, lets consider the following snippet:

function MainCtrl($scope, $resource) {
  var User = $resource('/users/:id'),
  $scope.user = User.get({ id: 42 });
}
<span ng-bind="user.name"></span>
Initially when the snippet above executes, the property user of the $scope object will be with value equal to an empty object ({}), which means that user.name will be undefined and nothing will be rendered. Internally AngularJS will keep reference to this empty object. Once the server returns response for the GET request, AngularJS will populate the object with the data, received from the server. During the next $digest loop AngularJS will detect change in $scope.user, which will lead to update of the view.

Active Record

The Active Record object is an object, which carries both data and behavior. Usually most of the data in these objects is persistent, responsibility of the Active Record object is to take care of the communication with the database in order to create, update, retrieve or delete the data. It may delegate this responsibility to lower level objects but calls to instance or static methods of the active record object cause the database communication.

Active Record

AngularJS defines a service called $resource. In the current version of AngularJS (1.2+) it is being distributed in module outside of the AngularJS’ core.

According to the AngularJS’ documentation $resource is:

A factory which creates a resource object that lets you interact with RESTful server-side data sources. The returned resource object has action methods which provide high-level behaviors without the need to interact with the low level $http service.

Here is how $resource could be used:

var User = $resource('/users/:id'),
    user = new User({
      name: 'foo',
      age : 42
    });

user.$save();

The call of $resource will create a constructor function for our model instances. Each of the model instances will have methods, which could be used for the different CRUD operations.

This way we can use the constructor function and its static methods by:

User.get({ userid: userid });

The code above will immediately return an empty object and keep reference to it. Once the response has been successfully returned and parsed, AngularJS will populate this object with the received data (see proxy).

You can find more details for $resource The magic of $resource and AngularJS’ documentation.

Since Martin Fowler states that

responsibility of the Active Record object is to take care of the communication with the databse in order to create…

$resource does not implement exactly the Active Record pattern, since it communicates with RESTful service instead of the database. Anyway, we can consider it as “Active Record like RESTful communication”.