Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created October 30, 2016 11:20
Providing Run Blocks Using A Service Constructor In Angular 2.1.1
// Import the core angular services.
import { APP_INITIALIZER } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { ErrorHandler } from "@angular/core";
import { Injectable } from "@angular/core";
import { NgModule } from "@angular/core";
// Import the application components and services.
import { AppComponent } from "./app.component";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
@Injectable()
export class OnRun {
// Because this is a "class" and not a Factory function, we can use the normal
// dependency-injection semantics. All we have to do is define Types here and those
// instances will be provided to the constructor.
constructor( errorHandler: ErrorHandler ) {
// CAUTION: Here, we are "hacking" the workflow. Instead of letting Angular use
// the OnRun class instance, we're explicitly overriding the constructor method's
// return value, passing back the "run block". This is a core feature of
// JavaScript's "newable" Functions (from MDN):
// --
// >> The object returned by the constructor function becomes the
// >> result of the whole new expression. If the constructor function
// >> doesn't explicitly return an object, the object created in step 1
// >> is used instead. (Normally constructors don't return a value,
// >> but they can choose to do so if they want to override the normal
// >> object creation process.)
// --
return( runblock );
// NOTE: This is the method that gets run at the end of the bootstrapping process.
function runblock() : void {
console.group( "Class Instance" );
console.log( "Run block generated by class instance (return value)." );
console.log( errorHandler );
console.groupEnd();
}
}
}
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
@NgModule({
bootstrap: [ AppComponent ],
imports: [ BrowserModule ],
providers: [
OnRun,
// Here, we are defining an app initializer or "run block" using a factory
// function. The factory function returns a Function reference which will be
// invoked at the end of the bootstrapping process. Notice that the factory
// function can use dependency-injection using the "deps" array.
{
provide: APP_INITIALIZER,
multi: true,
deps: [ ErrorHandler ],
useFactory: function( errorHandler: ErrorHandler ) : () => void {
return( runblock );
// NOTE: This is the method that gets run at the end of the
// bootstrapping process.
function runblock() : void {
console.group( "Factory Function" );
console.log( "Run block generated by Factory function." );
console.log( errorHandler );
console.groupEnd();
}
}
},
// As it turns out, we can also define app initializers as classes. Sort of.
// Ultimately, we still need to return a Function reference; but, we can leverage
// the Class mechanics to drive the dependency-injection as long as the class
// constructor still returns the Function reference that gets invoked at the end
// of the bootstrapping process.
{
provide: APP_INITIALIZER,
multi: true,
useClass: OnRun
}
],
declarations: [ AppComponent ]
})
export class AppModule {
// ... nothing to do here.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment