Keeping angularjs decoupled from an application - javascript

I'm planning out an application that ideally I'd like to keep decoupled from Angular, so all the dom interaction will go into an Angular layer but the core business logic will be kept in a standalone app that is totally unaware of Angular. The two will communicate via Angular services that are able to send messages to the core application.
The standalone app will most likely use requirejs to handle dependency injection.
What I'm unsure of is how to get a module that may be declared something like this:
define('AppInteractor', ['require'], function(requre){
// Set up interactor functionality
});
Into an Angular service.
My first though was to have some kind of adapter like this:
define(['AppInteractor', 'angular'], function(interactor, angular) {
var app = angular.module('appInteractor', []).service('AppInteractor', interactor);
});
This would register the AppInteractor as a service within an angular module, the problem with this approach seems to be that because requirejs loads things asynchronously the service hasn't been set when the angular code runs. It also seems to end up with angular loading twice which presumably also doesn't help matters.
I've seen a few articles covering loading all Angular components via require but I was hoping there might be simpler way to make this work.
Can anyone recommend how I might make this work?

If you are going to add a service after the main modules initialization, I recommend you add it to your application module
define(['AppInteractor', 'angular'], function(interactor, angular) {
// There is no second parameter, because we are getting an existing
// module, not creating a new one.
var app = angular.module('appModule');
app.service('AppInteractor', interactor);
});
Otherwise, if you want to group all your other logic in a different module, you will need to import the module and add it as a requirement of your application module.
define(['AppInteractorModule', 'angular'], function(interactorModule, angular) {
var app = angular.module('appModule', [interactorModule.name]);
});
I also recommend you use a tool like ES6 (6to5, traceur), browserify or Typescript for your module management, and then compile to AMD. I find it easier and cleaner for development.

Related

How to do effective dependency injection in Nodejs?

Let's start with some reference code
var express = require('express');
var app = express();
var session = require('express-session');
app.use(session({
store: require('connect-session-knex')()
}));
I have a couple questions here that I would like to answer in case you know the answer:
Everytime a require is call in Nodejs, is that named dependency injection? Or what is the real meaning of dependency injection?
The reason why I am asking this, is because I've been reading about Node, and I see people people talking about the module or module.export pattern, and I am confuse, the module is the same as dependency?
So, all I need is a clear explanation about dependency injection, and when/where you need to inject a dependency . . .
Dependency injection is somewhat the opposite of normal module design. In normal module design, a module uses require() to load in all the other modules that it needs with the goal of making it simple for the caller to use your module. The caller can just require() in your module and your module will load all the other things it needs.
With dependency injection, rather than the module loading the things it needs, the caller is required to pass in things (usually objects) that the module needs. This can make certain types of testing easier and it can make mocking certain things for testing purposes easier.
Everytime a require is call in Nodejs, is that named dependency
injection? Or what is the real meaning of dependency injection?
No. When a module does a require() to load it's own dependencies that is not dependency injection.
The reason why I am asking this, is because I've been reading about
Node, and I see people people talking about the module or
module.export pattern, and I am confuse, the module is the same as
dependency?
A module is not the same as a dependency. Normal module design allows you to require() just the module and get back a series of exports that you can use. The module itself handles the loading of its own dependencies (usually using require() internal to the module).
Here are a couple of articles that discuss some of the pros/cons of using dependency injection. As best I can tell the main advantage is to simplify unit testing by allowing dependent objects (like databases) to be more easily mocked.
When to use Dependency Injection
When is it not appropriate to use dependency injection
Why should we use dependency injection
A classic case for using a dependency injection is when a module depends upon a database interface. If the module loads it's own database, then that module is essentially hard-wired to that particular database. There is no architecture built into the module for the caller to specify what type of storage should be used.
If, however, the module is set up so that when a caller loads and initializes the module, it must pass in an object that implements a specific database API, then the caller is free to decide what type of database should be used. Any database that meets the contract of the API can be used. But, the burden is on the caller to pick and load a specific database. There can also be hybrid circumstances where a module has a built-in database that will be used by default, but the caller can supply their own object that will be used instead if it is provided in the module constructor or module initialization.
Imagine this code.
var someModule = require('pathToSomeModule');
someModule();
Here, we DEPEND not on the name, but on the path of that file. We are also using the SAME file every time.
Let's look at angular's way (for the client, i know, bear with me)
app.controller('someCtrl', function($scope) {
$scope.foo = 'bar';
});
I know client side js doesn't have file imports / exports, but it's the underlying concept that you should look at. Nowhere does this controller specify WHAT the $scope variable ACTUALLY is, it just knows that angular is giving it something CALLED $scope.
This is Inversion of Control
It is like saying, Don't call me, I'll call you
Now let's implement our original code with something like a service container (there are many different solutions to this, containers are not the only option)
// The only require statement
var container = require('pathToContainer')
var someModule = container.resolve('someModule');
someModule();
What did we accomplish here? Now, we only have to know ONE thing, the container (or whatever abstraction you choose). We have no idea what someModule actually is, or where it's source file is, just that it's what we got from the container. The benefit of this is that, if we want to use a different implementation of someModule, as long as it conforms to the same API as the orignal, we can just replace it ONE place in our ENTIRE app. The container. Now every module that calls someModule will get the new implementation. The idea is that when you make a module, you define the api that you use to interact with it. If different implementations all conform to a single api (or you write an adapter that conforms to it) then you can swap out implementations like dirty underwear and your app will just WORK.
This approach is not for everyone, and some people hate lugging around the container.
My personal opinion, I would rather code to an interface ( a consistent api between implentations ) than code to a concrete implementation.
An actual example of Dependency Injection in node.js
// In a file, far, far, away
module.exports = function(dependencyA, dependencyB) {
dependencyA();
dependencyB();
}
// In another file, the `caller`
// This is where the actual, concrete implementation is stored
var depA = someConcreteImplementation;
var depB = someOtherConcreteImplementation;
var someModule = require('pathToSomeModule');
someModule(depA, depB);
The downside to this, is now the caller needs to know what your dependencies are. Some are comforted by this and like it, others believe it's a hassle.
I prefer this next approach, personally.
If you aren't using babel, or something that changes your functions behind the scenes, you can use this approach to get the angular-style parameter-parsing
http://krasimirtsonev.com/blog/article/Dependency-injection-in-JavaScript
Then you can parse the function you get from require, and not use a container at all.
I use injection-js Dependency injection library for JavaScript and TypeScript with ts-node:
npm i -P injection-js
It's based on the angular2 injector so Injection is super simple.
Here is the typescript version from the README.
import 'reflect-metadata';
import { ReflectiveInjector, Injectable, Injector } from 'injection-js';
class Http {}
#Injectable()
class Service {
constructor(private http: Http) {}
}
#Injectable()
class Service2 {
constructor(private injector: Injector) {}
getService(): void {
console.log(this.injector.get(Service) instanceof Service);
}
createChildInjector(): void {
const childInjector = ReflectiveInjector.resolveAndCreate([
Service
], this.injector);
}
}
const injector = ReflectiveInjector.resolveAndCreate([
Service,
Http
]);
console.log(injector.get(Service) instanceof Service);

read or write file to filesystem with angular

I will read/write a file with angular from/to my hdd. I normaly use node module "fs". Whats the best practice to combine this module with angular to use it in node webkit?
Thanks!
Edit: (can't use require in angular to load npm modules. any ideas?)
.service("WindowService", WindowService);
function WindowService() {
this.gui = require('nw.gui');
}
i wrote this example, if you had any questions as to how things are working? you may also want to check out this as well, which the former example uses to work outside of the browser.
but since the main question is regarding the error involving the require function, i will elaborate. require is a function implemented by the node runtime, it was added because there was no way initially built into js to import code from fileA to fileB. so when your in the browser you dont need to require anything, just make sure you have the file added to the html ie: <script src="my/file.js"></script>. but if you really want to do require in the browser, just use browserfy.
I have similar experiences to you. I usually wrap modules to services and use it as normal angular service with DI.
This makes code more readable and maintanable. Also, when you want to change node module, you are changing it in one place.
for your project, i will look to
socket.io > for broadcast websocket, and update your angular scope...
shokidar > better than FS, with less bug than fs

How to properly import js files in meteor

I like keeping my javascript files as small as possible and using an architectural pattern. This usually means splitting my js files in Services, Controllers, Models, Views, etc.
Meteor automatically loads all js files. However every variable defined in any js file is processed as a local variable for that file. To be able to access them I have to define them like so:
//global
my_global_function = function(){
}
//not global
var my_global_function = function(){
}
//not global
function my_global_function(){
}
Defining a variable/function without the keyword var or function is not good practice. What are the possible alternatives?
The best option is to use ES2015 modules.
Meteor does not support modules natively yet, but there are packages that bring this support.
For example, universe:modules.
With modules you can import and export some variables/functions/classes/etc:
// module1.import.js
import alertSomething from './module2'
Meteor.startup(() => {
alertSomething();
});
// module2.import.js
export default function alertSomething() {
alert('something');
}
universe:modules is not the only solution, there are other similar projects. I love this one specially https://github.com/thereactivestack/kickstart-simple. It replaces Meteor's build system with WebPack's and enables hot-reloading if you use React.
UPDATE:
Meteor does support ES6 modules now
Since you seem very interested in proper architectural design, I would recommend looking at Meteor packages. Essentially, you have to declare any globally exposed variable in the package.js configuration, which is what you want: as little "leakage" as possible. Within a package, you can afford to be a little bit more sloppy, but you can still use var (and the absence of var) for more fine-grained control within a package. This can be done within Meteor right now.
You can find most information in the package documentation. The easiest way to get started is to create a package using meteor create --package [package-name]. This sets up a basic structure to play with. The api.export function is what controls exposed variables. See doc here.
Additionally, be careful with adding an unnecessary layer on top of the intrinsic Meteor architectural design. Templates are views, server side methods are services, etc. There are only some things that you don't get out of the box, so usually you'll add something like Astronomy or SimpleSchema.
Adding too much of your own architecture is probably going to end with you fighting the Meteor framework itself...

Thinking in Angular Way

I am working on project with more than 1500 HTML pages.
This project was previously implemented in jQuery and JS code. Now I have to revamp this SPA using AngularJS.
I have gone through basics of angularjs. We have several interaction on in our projects (Moving from one page to another).
Is <head ngapp="routingApp"> is the right place to configure the routing for whole project or can I define it separately for each module?
As the project also uses jQuery for bootstrap dependency does it make any sense just to include jQuery for bootstrap?
I would strongly discourage you from declaring all your routing in one file. It will lead to really big file & bad maintainability.
If you have such a big project I'll advise you to read the Google's recommendation for AngularJS structure first.
Then every developer will have a way to 'scope' his work within one module & it would be easier for him to understand it.
Moreover it would be much easier to disable/enable some modules just by excluding them from final composing&"compilation" phase.
E.g. you'll have a module that defines routes that can be reached within this module.
I strongly recommend using Gulp & Bower (you'll have to have Node.js) to manage you dependency management as well as composition/compilation phase management.
As a teaser here you have gulp scripts compilation for fractal structure:
gulp.task('scripts', function () {
var depJS = dependencies.bower.js.map(function (dep) { return config.bowerLib + dep; });
depJS = depJS.concat(dependencies.node.js.map(function (dep) { return config.nodeLib + dep; }));
var srcJS = ['app/modules/app.js', 'app/modules/**/*.module.js', 'app/modules/**/*.js'];
var libPipe = gulp.src(depJS)
.pipe(plumber())
.pipe(concat('lib.min.js'))
.pipe(size({title: 'js-before lib'}))
.pipe(gulpif(config.minimize.perform, uglify(config.minimize.js)))
.pipe(size({title: ' js-after lib'}))
.pipe(gulp.dest(config.scriptsOutDir));
var pipe = gulp.src(srcJS)
.pipe(plumber())
.pipe(concat('all.min.js'))
.pipe(size({title: 'js-before all'}))
.pipe(gulpif(config.minimize.perform, uglify(config.minimize.js)))
.pipe(size({title: ' js-after all'}))
.pipe(gulp.dest(config.scriptsOutDir));
});
The second question - AngularJS have jQLite inside it. When the jQuery is available the jQuery implementation is used. (side note: use jQuery/jqlite only in directives). It depends how vastly the jQuery library is used throughout your project & what methods are used. Can it be replaced by jqlite (limited jQuery) or can you just rewrite all jquery specific DOM/etc. manipulation by directives.
You've mentioned bootstrap - did you mean Twitter Bootstrap? If so, look at the AngularJS UI-Bootstrap
You can definetaly separate it in modules, look at https://github.com/angular-ui/ui-router.
1.) If you are asking if its right to define whole routing inside 1 index.html and one angular app , yes it is right place. It is purpose of SPA

Angular services and browserify

I am using AngularJS for a SPA, and I am using browserify to build my application. Now the question came up whether we should write Angular services in the classical way, or simply require them.
As Angular services are singletons, this could be easily done with require as well: Simply expose an object literal, and you're done. Factories are also possible, simply expose a function. And so on ...
The only disadvantage I can currently think of is that I am not able to access other real Angular services from such a file (like, e.g., $http), but with browserify in the background this does not seem to be that important. E.g., you could easily use Node.js's http module for that, thanks to browserify.
So what do you think of this? What are other advantages and disadvantages for this?
PS: Please note that I'm not asking for whether this is good or bad, as this is probably mainly subjective. I'm rather interested which opportunities appear, or which risks I have to deal with.
One disadvantage to doing this is writing unit tests. It will be difficult to mock your dependencies if you are simply requiring them rather than using Angular's dependency injection.
This is somewhat of a dealbreaker for me because one of the many benefits of using Angular is the testability of the framework.
It's bad.
Just use browserify to initially load in all the modules you need.
you miss out on $httpBackend
your code becomes harder to follow, ie, there is very rarely a point to reuse that directives controller
you miss out on $http interceptors
you miss it in being able to modify and interact with other injectables.
The only thing I'd use browserify/webpack/requirejs for in an angular app is two things:
creating js bundle
injecting templates as strings into the angular template cache as a module.
Personally this kind of approach is just a pointless complication.
If you require things like $http you won't have any way to inject dummy/mocks of those services during testing.
Although somewhere you will do the wiring between your super-duper service that needs $http and the place you need it.
The first thing that came into my mind is resolvers in routes. You can even have some helper methods to deal with declaring the same dependencies many times.
Imagine this module:
function SuperResource($http, pathExpression) {}
exports.SuperResource = SuperResource;
exports.superResourceFactory = function(pathExpression) {
return [
'$http',
function() {
return new SuperResource($http, pathExpression);
}];
};
Somewhere you will do:
var myModule = require('./myModule.js');
resolvers: {
usersResource: myModule.superResourceFactory('/users')
}
Or even you could have a user modules that defines the user resource:
var myModule = require('./myModule');
exports.userFactory = ['$http', function() {
return new myModule.SuperResource($http, pathExpression);
}
Yes, these are angular specific helpers in an otherwise angular free code, but at least they're isolated in their own method/name.

Categories