mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
refactor(delegateService): make more DRY, increase perf
This commit is contained in:
114
js/angular/service/delegateService.js
vendored
114
js/angular/service/delegateService.js
vendored
@@ -7,28 +7,6 @@ function delegateService(methodNames) {
|
||||
function trueFn() { return true; }
|
||||
|
||||
return ['$log', function($log) {
|
||||
var delegate = this;
|
||||
|
||||
var instances = this._instances = [];
|
||||
this._registerInstance = function(instance, handle, filterFn) {
|
||||
instance.$$delegateHandle = handle;
|
||||
instance.$$filterFn = filterFn || trueFn;
|
||||
instances.push(instance);
|
||||
|
||||
return function deregister() {
|
||||
var index = instances.indexOf(instance);
|
||||
if (index !== -1) {
|
||||
instances.splice(index, 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
this.$getByHandle = function(handle) {
|
||||
if (!handle) {
|
||||
return delegate;
|
||||
}
|
||||
return new InstanceForHandle(handle);
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a new object that will have all the methodNames given,
|
||||
@@ -46,67 +24,75 @@ function delegateService(methodNames) {
|
||||
* that will only try to fetch the controller with given handle
|
||||
* once the methods are actually called.
|
||||
*/
|
||||
function InstanceForHandle(handle) {
|
||||
function DelegateInstance(instances, handle) {
|
||||
this._instances = instances;
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
methodNames.forEach(function(methodName) {
|
||||
InstanceForHandle.prototype[methodName] = function() {
|
||||
DelegateInstance.prototype[methodName] = instanceMethodCaller(methodName);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* The delegate service (eg $ionicNavBarDelegate) is just an instance
|
||||
* with a non-defined handle, a couple extra methods for registering
|
||||
* and narrowing down to a specific handle.
|
||||
*/
|
||||
function DelegateService() {
|
||||
this._instances = [];
|
||||
}
|
||||
DelegateService.prototype = DelegateInstance.prototype;
|
||||
DelegateService.prototype._registerInstance = function(instance, handle, filterFn) {
|
||||
var instances = this._instances;
|
||||
instance.$$delegateHandle = handle;
|
||||
instance.$$filterFn = filterFn || trueFn;
|
||||
instances.push(instance);
|
||||
|
||||
return function deregister() {
|
||||
var index = instances.indexOf(instance);
|
||||
if (index !== -1) {
|
||||
instances.splice(index, 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
DelegateService.prototype.$getByHandle = function(handle) {
|
||||
return new DelegateInstance(this._instances, handle);
|
||||
};
|
||||
|
||||
return new DelegateService();
|
||||
|
||||
function instanceMethodCaller(methodName) {
|
||||
return function caller() {
|
||||
var handle = this.handle;
|
||||
var args = arguments;
|
||||
var matchingInstancesFound = 0;
|
||||
var finalResult;
|
||||
var result;
|
||||
var foundInstancesCount = 0;
|
||||
var returnValue;
|
||||
|
||||
//This logic is repeated below; we could factor some of it out to a function
|
||||
//but don't because it lets this method be more performant (one loop versus 2)
|
||||
instances.forEach(function(instance) {
|
||||
if (instance.$$delegateHandle === handle && instance.$$filterFn(instance)) {
|
||||
matchingInstancesFound++;
|
||||
result = instance[methodName].apply(instance, args);
|
||||
this._instances.forEach(function(instance) {
|
||||
if ((!handle || handle == instance.$$delegateHandle) && instance.$$filterFn(instance)) {
|
||||
foundInstancesCount++;
|
||||
var ret = instance[methodName].apply(instance, args);
|
||||
//Only return the value from the first call
|
||||
if (matchingInstancesFound === 1) {
|
||||
finalResult = result;
|
||||
if (foundInstancesCount === 1) {
|
||||
returnValue = ret;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!matchingInstancesFound) {
|
||||
if (!foundInstancesCount && handle) {
|
||||
return $log.warn(
|
||||
'Delegate for handle "' + this.handle + '" could not find a ' +
|
||||
'corresponding element with delegate-handle="' + this.handle + '"! ' +
|
||||
'Delegate for handle "' + handle + '" could not find a ' +
|
||||
'corresponding element with delegate-handle="' + handle + '"! ' +
|
||||
methodName + '() was not called!\n' +
|
||||
'Possible cause: If you are calling ' + methodName + '() immediately, and ' +
|
||||
'your element with delegate-handle="' + this.handle + '" is a child of your ' +
|
||||
'your element with delegate-handle="' + handle + '" is a child of your ' +
|
||||
'controller, then your element may not be compiled yet. Put a $timeout ' +
|
||||
'around your call to ' + methodName + '() and try again.'
|
||||
);
|
||||
}
|
||||
|
||||
return finalResult;
|
||||
return returnValue;
|
||||
};
|
||||
}
|
||||
|
||||
delegate[methodName] = function() {
|
||||
var args = arguments;
|
||||
var matchingInstancesFound = 0;
|
||||
var finalResult;
|
||||
var result;
|
||||
|
||||
//This logic is repeated above
|
||||
instances.forEach(function(instance, index) {
|
||||
if (instance.$$filterFn(instance)) {
|
||||
matchingInstancesFound++;
|
||||
result = instance[methodName].apply(instance, args);
|
||||
//Only return the value from the first call
|
||||
if (matchingInstancesFound === 1) {
|
||||
finalResult = result;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return finalResult;
|
||||
};
|
||||
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -125,11 +125,6 @@ describe('DelegateFactory', function() {
|
||||
expect(delegate.fn()).toBe('ret1');
|
||||
});
|
||||
|
||||
it('$getByHandle should return this for blank handle', function() {
|
||||
var delegate = setup();
|
||||
expect(delegate.$getByHandle()).toBe(delegate);
|
||||
});
|
||||
|
||||
describe('$getByHandle', function() {
|
||||
var delegate, instance1, instance2, instance3;
|
||||
beforeEach(function() {
|
||||
|
||||
Reference in New Issue
Block a user