feat(injector): implement async dependencies
This commit is contained in:
parent
a814d48bbc
commit
14af5a0a42
|
@ -5,4 +5,11 @@ export class Inject {
|
||||||
constructor(token){
|
constructor(token){
|
||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class InjectFuture {
|
||||||
|
@CONST()
|
||||||
|
constructor(token){
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
import {Type} from 'facade/lang';
|
import {Type} from 'facade/lang';
|
||||||
import {List, MapWrapper, ListWrapper} from 'facade/collection';
|
import {List, MapWrapper, ListWrapper} from 'facade/collection';
|
||||||
import {Reflector} from './reflector';
|
import {Reflector} from './reflector';
|
||||||
import {Key} from './key';
|
import {Key, Dependency} from './key';
|
||||||
|
|
||||||
export class Binding {
|
export class Binding {
|
||||||
constructor(key:Key, factory:Function, dependencies:List, async) {
|
constructor(key:Key, factory:Function, dependencies:List, providedAsFuture) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.dependencies = dependencies;
|
this.dependencies = dependencies;
|
||||||
this.async = async;
|
this.providedAsFuture = providedAsFuture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export class BindingBuilder {
|
||||||
return new Binding(
|
return new Binding(
|
||||||
Key.get(this.token),
|
Key.get(this.token),
|
||||||
this.reflector.factoryFor(type),
|
this.reflector.factoryFor(type),
|
||||||
this._wrapKeys(this.reflector.dependencies(type)),
|
this.reflector.dependencies(type),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ export class BindingBuilder {
|
||||||
return new Binding(
|
return new Binding(
|
||||||
Key.get(this.token),
|
Key.get(this.token),
|
||||||
this.reflector.convertToFactory(factoryFunction),
|
this.reflector.convertToFactory(factoryFunction),
|
||||||
this._wrapKeys(dependencies),
|
this._constructDependencies(dependencies),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -53,12 +53,12 @@ export class BindingBuilder {
|
||||||
return new Binding(
|
return new Binding(
|
||||||
Key.get(this.token),
|
Key.get(this.token),
|
||||||
this.reflector.convertToFactory(factoryFunction),
|
this.reflector.convertToFactory(factoryFunction),
|
||||||
this._wrapKeys(dependencies),
|
this._constructDependencies(dependencies),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_wrapKeys(deps:List) {
|
_constructDependencies(deps:List) {
|
||||||
return ListWrapper.map(deps, (t) => Key.get(t));
|
return ListWrapper.map(deps, (t) => new Dependency(Key.get(t), false));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,13 @@ function constructResolvingPath(keys: List) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ProviderError extends Error {
|
class DIError extends Error {
|
||||||
|
toString() {
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ProviderError extends DIError {
|
||||||
constructor(key:Key, constructResolvingMessage:Function){
|
constructor(key:Key, constructResolvingMessage:Function){
|
||||||
this.keys = [key];
|
this.keys = [key];
|
||||||
this.constructResolvingMessage = constructResolvingMessage;
|
this.constructResolvingMessage = constructResolvingMessage;
|
||||||
|
@ -23,10 +29,6 @@ export class ProviderError extends Error {
|
||||||
ListWrapper.push(this.keys, key);
|
ListWrapper.push(this.keys, key);
|
||||||
this.message = this.constructResolvingMessage(this.keys);
|
this.message = this.constructResolvingMessage(this.keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
|
||||||
return this.message;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NoProviderError extends ProviderError {
|
export class NoProviderError extends ProviderError {
|
||||||
|
@ -38,7 +40,7 @@ export class NoProviderError extends ProviderError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AsyncProviderError extends ProviderError {
|
export class AsyncBindingError extends ProviderError {
|
||||||
constructor(key:Key){
|
constructor(key:Key){
|
||||||
super(key, function(keys:List) {
|
super(key, function(keys:List) {
|
||||||
var first = stringify(ListWrapper.first(keys).token);
|
var first = stringify(ListWrapper.first(keys).token);
|
||||||
|
@ -48,12 +50,14 @@ export class AsyncProviderError extends ProviderError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InvalidBindingError extends Error {
|
export class InvalidBindingError extends DIError {
|
||||||
constructor(binding){
|
constructor(binding){
|
||||||
this.message = `Invalid binding ${binding}`;
|
this.message = `Invalid binding ${binding}`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toString() {
|
export class NoAnnotationError extends DIError {
|
||||||
return this.message;
|
constructor(type){
|
||||||
|
this.message = `Cannot resolve all parameters for ${stringify(type)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import {Map, List, MapWrapper, ListWrapper} from 'facade/collection';
|
import {Map, List, MapWrapper, ListWrapper} from 'facade/collection';
|
||||||
import {Binding, BindingBuilder, bind} from './binding';
|
import {Binding, BindingBuilder, bind} from './binding';
|
||||||
import {ProviderError, NoProviderError, InvalidBindingError, AsyncProviderError} from './exceptions';
|
import {ProviderError, NoProviderError, InvalidBindingError, AsyncBindingError} from './exceptions';
|
||||||
import {Type, isPresent, isBlank} from 'facade/lang';
|
import {Type, isPresent, isBlank} from 'facade/lang';
|
||||||
import {Future, FutureWrapper} from 'facade/async';
|
import {Future, FutureWrapper} from 'facade/async';
|
||||||
import {Key} from './key';
|
import {Key} from './key';
|
||||||
|
@ -39,21 +39,19 @@ export class Injector {
|
||||||
return this._getByKey(key, true);
|
return this._getByKey(key, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getByKey(key:Key, async) {
|
_getByKey(key:Key, returnFuture) {
|
||||||
var keyId = key.id;
|
var keyId = key.id;
|
||||||
if (key.token === Injector) return this._injector(async);
|
if (key.token === Injector) return this._injector(returnFuture);
|
||||||
|
|
||||||
var instance = this._get(this._instances, keyId);
|
var instance = this._get(this._instances, keyId);
|
||||||
if (isPresent(instance)) return instance;
|
if (isPresent(instance)) return instance;
|
||||||
|
|
||||||
var binding = this._get(this._bindings, keyId);
|
var binding = this._get(this._bindings, keyId);
|
||||||
|
|
||||||
if (isPresent(binding)) {
|
if (isPresent(binding)) {
|
||||||
return this._instantiate(key, binding, async);
|
return this._instantiate(key, binding, returnFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(this._parent)) {
|
if (isPresent(this._parent)) {
|
||||||
return this._parent._getByKey(key, async);
|
return this._parent._getByKey(key, returnFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NoProviderError(key);
|
throw new NoProviderError(key);
|
||||||
|
@ -65,8 +63,8 @@ export class Injector {
|
||||||
return inj;
|
return inj;
|
||||||
}
|
}
|
||||||
|
|
||||||
_injector(async){
|
_injector(returnFuture){
|
||||||
return async ? FutureWrapper.value(this) : this;
|
return returnFuture ? FutureWrapper.value(this) : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
_get(list:List, index){
|
_get(list:List, index){
|
||||||
|
@ -74,39 +72,40 @@ export class Injector {
|
||||||
return ListWrapper.get(list, index);
|
return ListWrapper.get(list, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
_instantiate(key:Key, binding:Binding, async) {
|
_instantiate(key:Key, binding:Binding, returnFuture) {
|
||||||
if (binding.async && !async) {
|
if (binding.providedAsFuture && !returnFuture) {
|
||||||
throw new AsyncProviderError(key);
|
throw new AsyncBindingError(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (async) {
|
if (returnFuture) {
|
||||||
return this._instantiateAsync(key, binding, async);
|
return this._instantiateAsync(key, binding);
|
||||||
} else {
|
} else {
|
||||||
return this._instantiateSync(key, binding, async);
|
return this._instantiateSync(key, binding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_instantiateSync(key:Key, binding:Binding, async) {
|
_instantiateSync(key:Key, binding:Binding) {
|
||||||
try {
|
try {
|
||||||
var deps = ListWrapper.map(binding.dependencies, d => this._getByKey(d, false));
|
var deps = ListWrapper.map(binding.dependencies, d => this._getByKey(d.key, d.asFuture));
|
||||||
var instance = binding.factory(deps);
|
var instance = binding.factory(deps);
|
||||||
ListWrapper.set(this._instances, key.id, instance);
|
ListWrapper.set(this._instances, key.id, instance);
|
||||||
if (!binding.async && async) {
|
|
||||||
return FutureWrapper.value(instance);
|
|
||||||
}
|
|
||||||
return instance;
|
return instance;
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ProviderError) e.addKey(key);
|
if (e instanceof ProviderError) e.addKey(key);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_instantiateAsync(key:Key, binding:Binding, async):Future {
|
_instantiateAsync(key:Key, binding:Binding):Future {
|
||||||
var instances = this._createInstances();
|
var instances = this._createInstances();
|
||||||
var futures = ListWrapper.map(binding.dependencies, d => this._getByKey(d, true));
|
var futures = ListWrapper.map(binding.dependencies, d => this._getByKey(d.key, true));
|
||||||
return FutureWrapper.wait(futures).
|
return FutureWrapper.wait(futures).
|
||||||
then(binding.factory).
|
then(binding.factory).
|
||||||
|
catch(function(e) {
|
||||||
|
console.log('sdfsdfsd', e)
|
||||||
|
//e.addKey(key)
|
||||||
|
//return e;
|
||||||
|
}).
|
||||||
then(function(instance) {
|
then(function(instance) {
|
||||||
ListWrapper.set(instances, key.id, instance);
|
ListWrapper.set(instances, key.id, instance);
|
||||||
return instance
|
return instance
|
||||||
|
|
|
@ -3,6 +3,14 @@ import {MapWrapper} from 'facade/collection';
|
||||||
var _allKeys = {};
|
var _allKeys = {};
|
||||||
var _id = 0;
|
var _id = 0;
|
||||||
|
|
||||||
|
//TODO: vsavkin: move to binding once cyclic deps are supported
|
||||||
|
export class Dependency {
|
||||||
|
constructor(key:Key, asFuture){
|
||||||
|
this.key = key;
|
||||||
|
this.asFuture = asFuture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Key {
|
export class Key {
|
||||||
constructor(token, id) {
|
constructor(token, id) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
library facade.di.reflector;
|
library facade.di.reflector;
|
||||||
|
|
||||||
import 'dart:mirrors';
|
import 'dart:mirrors';
|
||||||
import 'annotations.dart' show Inject;
|
import 'annotations.dart' show Inject, InjectFuture;
|
||||||
|
import 'key.dart' show Key, Dependency;
|
||||||
|
import 'exceptions.dart' show NoAnnotationError;
|
||||||
|
|
||||||
class Reflector {
|
class Reflector {
|
||||||
factoryFor(Type type) {
|
factoryFor(Type type) {
|
||||||
|
@ -27,26 +29,19 @@ class Reflector {
|
||||||
return new List.generate(ctor.parameters.length, (int pos) {
|
return new List.generate(ctor.parameters.length, (int pos) {
|
||||||
ParameterMirror p = ctor.parameters[pos];
|
ParameterMirror p = ctor.parameters[pos];
|
||||||
|
|
||||||
if (p.type.qualifiedName == #dynamic) {
|
final metadata = p.metadata.map((m) => m.reflectee);
|
||||||
var name = MirrorSystem.getName(p.simpleName);
|
|
||||||
throw "Error getting params for '$type': "
|
|
||||||
"The '$name' parameter must be typed";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.type is TypedefMirror) {
|
var inject = metadata.where((m) => m is Inject);
|
||||||
throw "Typedef '${p.type}' in constructor "
|
var injectFuture = metadata.where((m) => m is InjectFuture);
|
||||||
"'${classMirror.simpleName}' is not supported.";
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassMirror pTypeMirror = (p.type as ClassMirror);
|
|
||||||
var pType = pTypeMirror.reflectedType;
|
|
||||||
|
|
||||||
final inject = p.metadata.map((m) => m.reflectee).where((m) => m is Inject);
|
|
||||||
|
|
||||||
if (inject.isNotEmpty) {
|
if (inject.isNotEmpty) {
|
||||||
return inject.first.token;
|
return new Dependency(Key.get(inject.first.token), false);
|
||||||
|
} else if (injectFuture.isNotEmpty) {
|
||||||
|
return new Dependency(Key.get(injectFuture.first.token), true);
|
||||||
|
} else if (p.type.qualifiedName != #dynamic) {
|
||||||
|
return new Dependency(Key.get(p.type.reflectedType), false);
|
||||||
} else {
|
} else {
|
||||||
return pType;
|
throw new NoAnnotationError(type);
|
||||||
}
|
}
|
||||||
}, growable:false);
|
}, growable:false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import {Type} from 'facade/lang';
|
import {Type, isPresent} from 'facade/lang';
|
||||||
import {Inject} from './annotations';
|
import {Inject, InjectFuture} from './annotations';
|
||||||
|
import {Dependency, Key} from './key';
|
||||||
|
import {NoAnnotationError} from './exceptions';
|
||||||
|
|
||||||
export class Reflector {
|
export class Reflector {
|
||||||
factoryFor(type:Type) {
|
factoryFor(type:Type) {
|
||||||
|
@ -12,24 +14,34 @@ export class Reflector {
|
||||||
|
|
||||||
dependencies(type:Type) {
|
dependencies(type:Type) {
|
||||||
var p = type.parameters;
|
var p = type.parameters;
|
||||||
if (p == undefined) return [];
|
if (p == undefined && type.length == 0) return [];
|
||||||
return type.parameters.map((p) => this._extractToken(p));
|
if (p == undefined) throw new NoAnnotationError(type);
|
||||||
|
return type.parameters.map((p) => this._extractToken(type, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
_extractToken(annotations) {
|
_extractToken(constructedType:Type, annotations) {
|
||||||
var type, inject;
|
var type;
|
||||||
|
|
||||||
for (var paramAnnotation of annotations) {
|
for (var paramAnnotation of annotations) {
|
||||||
if (isFunction(paramAnnotation)) {
|
if (paramAnnotation instanceof Type) {
|
||||||
type = paramAnnotation;
|
type = paramAnnotation;
|
||||||
|
|
||||||
} else if (paramAnnotation instanceof Inject) {
|
} else if (paramAnnotation instanceof Inject) {
|
||||||
inject = paramAnnotation.token;
|
return this._createDependency(paramAnnotation.token, false);
|
||||||
|
|
||||||
|
} else if (paramAnnotation instanceof InjectFuture) {
|
||||||
|
return this._createDependency(paramAnnotation.token, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return inject != undefined ? inject : type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFunction(value) {
|
if (isPresent(type)) {
|
||||||
return typeof value === 'function';
|
return this._createDependency(type, false);
|
||||||
}
|
} else {
|
||||||
|
throw new NoAnnotationError(constructedType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_createDependency(token, asFuture):Dependency {
|
||||||
|
return new Dependency(Key.get(token), asFuture);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import {ddescribe, describe, it, iit, xit, expect, beforeEach} from 'test_lib/test_lib';
|
import {ddescribe, describe, it, iit, xit, expect, beforeEach} from 'test_lib/test_lib';
|
||||||
import {Injector, Inject, bind, Key} from 'di/di';
|
import {Injector, Inject, InjectFuture, bind, Key} from 'di/di';
|
||||||
import {Future, FutureWrapper} from 'facade/async';
|
import {Future, FutureWrapper} from 'facade/async';
|
||||||
|
|
||||||
class UserList {}
|
class UserList {}
|
||||||
|
@ -10,69 +10,108 @@ function fetchUsers() {
|
||||||
|
|
||||||
class SynchronousUserList {}
|
class SynchronousUserList {}
|
||||||
|
|
||||||
|
|
||||||
class UserController {
|
class UserController {
|
||||||
constructor(list:UserList) {
|
constructor(list:UserList) {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AsyncUserController {
|
||||||
|
constructor(@InjectFuture(UserList) userList) {
|
||||||
|
this.userList = userList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function main () {
|
export function main () {
|
||||||
describe("async injection", function () {
|
describe("async injection", function () {
|
||||||
it('should return a future', function() {
|
|
||||||
var injector = new Injector([
|
|
||||||
bind(UserList).toAsyncFactory([], fetchUsers)
|
|
||||||
]);
|
|
||||||
var p = injector.asyncGet(UserList);
|
|
||||||
expect(p).toBeFuture();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw when instantiating async provider synchronously', function() {
|
describe("asyncGet", function () {
|
||||||
var injector = new Injector([
|
it('should return a future', function() {
|
||||||
bind(UserList).toAsyncFactory([], fetchUsers)
|
var injector = new Injector([
|
||||||
]);
|
bind(UserList).toAsyncFactory([], fetchUsers)
|
||||||
|
]);
|
||||||
|
var p = injector.asyncGet(UserList);
|
||||||
|
expect(p).toBeFuture();
|
||||||
|
});
|
||||||
|
|
||||||
expect(() => injector.get(UserList))
|
it('should return a future when if the binding is sync', function() {
|
||||||
.toThrowError('Cannot instantiate UserList synchronously. It is provided as a future!');
|
var injector = new Injector([
|
||||||
});
|
SynchronousUserList
|
||||||
|
]);
|
||||||
|
var p = injector.asyncGet(SynchronousUserList);
|
||||||
|
expect(p).toBeFuture();
|
||||||
|
});
|
||||||
|
|
||||||
it('should return a future even if the provider is sync', function() {
|
it('should return the injector', function() {
|
||||||
var injector = new Injector([
|
var injector = new Injector([]);
|
||||||
SynchronousUserList
|
var p = injector.asyncGet(Injector);
|
||||||
]);
|
expect(p).toBeFuture();
|
||||||
var p = injector.asyncGet(SynchronousUserList);
|
});
|
||||||
expect(p).toBeFuture();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should provide itself', function() {
|
it('should return a future when instantiating a sync binding ' +
|
||||||
var injector = new Injector([]);
|
'with an async dependency', function(done) {
|
||||||
var p = injector.asyncGet(Injector);
|
var injector = new Injector([
|
||||||
expect(p).toBeFuture();
|
bind(UserList).toAsyncFactory([], fetchUsers),
|
||||||
});
|
UserController
|
||||||
|
]);
|
||||||
|
|
||||||
it('should return a future when a dependency is async', function(done) {
|
injector.asyncGet(UserController).then(function(userController) {
|
||||||
var injector = new Injector([
|
expect(userController).toBeAnInstanceOf(UserController);
|
||||||
bind(UserList).toAsyncFactory([], fetchUsers),
|
expect(userController.list).toBeAnInstanceOf(UserList);
|
||||||
UserController
|
done();
|
||||||
]);
|
});
|
||||||
|
|
||||||
injector.asyncGet(UserController).then(function(userController) {
|
|
||||||
expect(userController).toBeAnInstanceOf(UserController);
|
|
||||||
expect(userController.list).toBeAnInstanceOf(UserList);
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when a dependency is async', function() {
|
describe("get", function () {
|
||||||
var injector = new Injector([
|
it('should throw when instantiating an async binding', function() {
|
||||||
bind(UserList).toAsyncFactory([], fetchUsers),
|
var injector = new Injector([
|
||||||
UserController
|
bind(UserList).toAsyncFactory([], fetchUsers)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(() => injector.get(UserController))
|
expect(() => injector.get(UserList))
|
||||||
.toThrowError('Cannot instantiate UserList synchronously. It is provided as a future! (UserController -> UserList)');
|
.toThrowError('Cannot instantiate UserList synchronously. It is provided as a future!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw when instantiating a sync binding with an dependency', function() {
|
||||||
|
var injector = new Injector([
|
||||||
|
bind(UserList).toAsyncFactory([], fetchUsers),
|
||||||
|
UserController
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(() => injector.get(UserController))
|
||||||
|
.toThrowError('Cannot instantiate UserList synchronously. It is provided as a future! (UserController -> UserList)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should resolve synchronously when an async dependency requested as a future', function() {
|
||||||
|
var injector = new Injector([
|
||||||
|
bind(UserList).toAsyncFactory([], fetchUsers),
|
||||||
|
AsyncUserController
|
||||||
|
]);
|
||||||
|
var controller = injector.get(AsyncUserController);
|
||||||
|
|
||||||
|
expect(controller).toBeAnInstanceOf(AsyncUserController);
|
||||||
|
expect(controller.userList).toBeFuture();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should wrap sync dependencies into futures if required', function() {
|
||||||
|
var injector = new Injector([
|
||||||
|
bind(UserList).toFactory([], () => new UserList()),
|
||||||
|
AsyncUserController
|
||||||
|
]);
|
||||||
|
var controller = injector.get(AsyncUserController);
|
||||||
|
|
||||||
|
expect(controller).toBeAnInstanceOf(AsyncUserController);
|
||||||
|
expect(controller.userList).toBeFuture();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// InjectFuture toFactory([@AsyncInject(UserList)], (userListFuutre)]
|
||||||
|
// InjectFuture toFactory((@AsyncInject(UsrList) userListFuutre) => ]
|
||||||
|
|
||||||
// resolve exceptions and async
|
// resolve exceptions and async
|
||||||
|
// do not construct two instances of the same async dependency if there is one in progress
|
||||||
|
// cycles
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import {describe, it, expect, beforeEach} from 'test_lib/test_lib';
|
import {describe, it, iit, expect, beforeEach} from 'test_lib/test_lib';
|
||||||
import {Injector, Inject, bind} from 'di/di';
|
import {Injector, Inject, bind} from 'di/di';
|
||||||
|
|
||||||
class Engine {}
|
class Engine {}
|
||||||
|
@ -33,6 +33,10 @@ class CarWithInject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NoAnnotations {
|
||||||
|
constructor(secretDependency){}
|
||||||
|
}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('injector', function() {
|
describe('injector', function() {
|
||||||
it('should instantiate a class without dependencies', function() {
|
it('should instantiate a class without dependencies', function() {
|
||||||
|
@ -58,6 +62,11 @@ export function main() {
|
||||||
expect(car.engine).toBeAnInstanceOf(TurboEngine);
|
expect(car.engine).toBeAnInstanceOf(TurboEngine);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw when no type and not @Inject', function () {
|
||||||
|
expect(() => new Injector([NoAnnotations])).toThrowError(
|
||||||
|
'Cannot resolve all parameters for NoAnnotations');
|
||||||
|
});
|
||||||
|
|
||||||
it('should cache instances', function() {
|
it('should cache instances', function() {
|
||||||
var injector = new Injector([Engine]);
|
var injector = new Injector([Engine]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue