completed the splitting of _wrap_route_with_prep.js

This commit is contained in:
Spencer Alger 2014-07-16 11:43:18 -07:00
parent 8db1664fbd
commit f092f5cdf7
9 changed files with 52 additions and 107 deletions

View file

@ -3,7 +3,7 @@ define(function (require) {
var _ = require('lodash');
var nextTick = require('utils/next_tick');
return function SourceAbstractFactory(Private, Promise, timefilter) {
return function SourceAbstractFactory(Private, Promise, PromiseEmitter, timefilter) {
var pendingRequests = Private(require('components/courier/_pending_requests'));
var errorHandlers = Private(require('components/courier/_error_handlers'));
var fetch = Private(require('components/courier/fetch/fetch'));
@ -106,7 +106,7 @@ define(function (require) {
*/
SourceAbstract.prototype.onResults = function (handler) {
var source = this;
return new Promise.emitter(function (resolve, reject, defer) {
return new PromiseEmitter(function (resolve, reject, defer) {
source._createRequest(defer);
}, handler);
};

View file

@ -6,7 +6,7 @@ define(function (require) {
var module = require('modules').get('kibana/global_state');
module.service('globalState', function (Private, $rootScope, $route, $injector, Promise) {
module.service('globalState', function (Private, $rootScope, $route, $injector, Promise, PromiseEmitter) {
var globalState = this;
var setupSync = Private(require('components/state_management/_state_sync'));
@ -41,13 +41,13 @@ define(function (require) {
});
globalState.onUpdate = function (handler) {
return new Promise.emitter(function (resolve, reject, defer) {
return new PromiseEmitter(function (resolve, reject, defer) {
updateListeners.push(defer);
}, handler);
};
globalState.onAppUpdate = function (handler) {
return new Promise.emitter(function (resolve, reject, defer) {
return new PromiseEmitter(function (resolve, reject, defer) {
app.listeners.push(defer);
}, handler);
};

View file

@ -17,7 +17,7 @@ define(function (require) {
require('angular-bootstrap');
require('utils/private');
require('services/private');
var module = require('modules').get('kibana/controllers', ['ui.bootstrap']);

View file

@ -20,7 +20,7 @@ define(function (require) {
return function () { return 'pm_' + i++; };
}());
var module = require('modules').get('kibana/utils');
var module = require('modules').get('kibana/services');
module.service('Private', function ($injector) {
// one cache per instance of the Private service
var cache = {};

View file

@ -6,7 +6,11 @@ define(function (require) {
// Provides a tiny subset of the excelent API from
// bluebird, reimplemented using the $q service
module.service('Promise', function ($q, $timeout) {
'use strict';
function Promise(fn) {
if (typeof this === 'undefined') throw new Error('Promise constructor must be called with "new"');
var defer = $q.defer();
try {
fn(defer.resolve, defer.reject, defer);
@ -46,8 +50,12 @@ define(function (require) {
return obj && typeof obj.then === 'function';
};
return Promise;
});
module.factory('PromiseEmitter', function (Promise) {
/**
* Create a promise that uses our "event" like pattern.
* Create a function that uses an "event" like pattern for promises.
*
* When a single argument is passed, this will behave just like calling `new Promise(fn)`,
* but when a second arguemnt is passed, the fn will be used to recreate a promise eveytime
@ -98,18 +106,18 @@ define(function (require) {
* time this promise is resolved
* @return {Promise}
*/
Promise.emitter = function (fn, handler) {
var prom = Promise(fn);
function PromiseEmitter(fn, handler) {
var prom = new Promise(fn);
if (handler) {
prom.then(handler).then(function recurse() {
return Promise(fn).then(handler).then(recurse);
return new Promise(fn).then(handler).then(recurse);
});
}
return prom;
};
}
return Promise;
return PromiseEmitter;
});
});

View file

@ -87,19 +87,15 @@ define(function (require) {
count = count || 0;
if (count > 3) {
// catch all version
return function () {
return fn.apply(context, [].slice.call(arguments, 0, count));
};
}
// shortcuts for common paths
// !!!! PLEASE don't use more than two arg
if (count === 0) return function () { return fn.call(context); };
if (count === 1) return function (a) { return fn.call(context, a); };
if (count === 2) return function (a, b) { return fn.call(context, a, b); };
// shortcuts for common path
return function (a, b, c) {
if (count === 0) return fn.call(context);
if (count === 1) return fn.call(context, a);
if (count === 2) return fn.call(context, a, b);
if (count === 3) return fn.call(context, a, b, c);
// catch all version
return function () {
return fn.apply(context, [].slice.call(arguments, 0, count));
};
}
});

View file

@ -3,7 +3,7 @@ define(function (require) {
var _ = require('lodash');
var WorkQueue = require('utils/routes/_work_queue');
var errors = require('errors');
function wrapRouteWithPrep(route) {
if (!route.resolve && route.redirectTo) return;
@ -13,10 +13,10 @@ define(function (require) {
userWork.limit = _.keys(route.resolve).length;
var resolve = {
__prep__: function (Promise, $route, $injector, Notifier) {
return $injector.invoke(wrapRouteWithPrep._oneTimeSetup).then(function () {
return $injector.invoke(wrapRouteWithPrep._setupComplete);
})
__prep__: function (Private, Promise, $route, $injector, Notifier) {
var setup = Private(require('utils/routes/_setup'));
return setup.routeSetupWork()
.then(function () {
// wait for the queue to fill up, then do all the work
var defer = Promise.defer();
@ -50,35 +50,5 @@ define(function (require) {
route.resolve = resolve;
}
// broken out so that it can be tested
wrapRouteWithPrep._oneTimeSetup = function ($q, kbnSetup, config) {
var prom = $q.all([
kbnSetup(),
config.init(),
]);
// override setup to only return the promise
wrapRouteWithPrep._oneTimeSetup = function () { return prom; };
return prom;
};
// broken out so that it can be tested
wrapRouteWithPrep._setupComplete = function ($route, indexPatterns, config) {
if (!$route.current.$$route.originalPath.match(/settings\/indices/)) {
// always check for existing ids first
return indexPatterns.getIds()
.then(function (patterns) {
if (!patterns || patterns.length === 0) {
throw new errors.NoDefinedIndexPatterns();
}
if (!config.get('defaultIndex')) {
throw new NoDefaultIndexPattern();
}
});
}
};
return wrapRouteWithPrep;
});

View file

@ -3,6 +3,8 @@ define(function (require) {
var wrapRouteWithPrep = require('utils/routes/_wrap_route_with_prep');
require('components/setup/setup');
require('services/promises');
require('modules').get('kibana/controllers')
.config(function ($provide) {
// decorate the $route object to include a change and changeUrl method

View file

@ -1,45 +1,21 @@
define(function (require) {
var routes = require('routes');
var RouteManager = require('routes').RouteManager;
var getRouteProvider = require('./_get_route_provider');
var wrapRouteWithPrep = require('utils/routes/_wrap_route_with_prep');
var Promise = require('bluebird');
var _ = require('lodash');
var stub = require('test_utils/auto_release_sinon').stub;
require('services/private');
var routes;
return function () {
describe('wrapRouteWithPrep fn', function () {
require('test_utils/no_digest_promises').activateForSuite();
var $injector;
beforeEach(function (_$injector_) { $injector = _$injector_; });
it('adds a __prep__ resolve, which does some setup work, then some user work', function () {
var i = 0;
var next = function () {
return _.partial(Promise.resolve, i++);
};
stub(wrapRouteWithPrep, 'oneTimeSetup', Promise.resolve);
stub(wrapRouteWithPrep, 'setupComplete', Promise.resolve);
var route = {
resolve: {
userWork1: next,
userWork2: next,
userWork3: next,
userWork4: next
}
};
wrapRouteWithPrep(route);
return Promise.props(_.mapValues(route.resolve, _.limit($injector.invoke, 1)))
.then(function (resolve) {
expect(resolve.__prep__).to.be('delayed_first');
expect(resolve.userWork1).to.be.above(0);
expect(resolve.userWork2).to.be.above(0);
expect(resolve.userWork3).to.be.above(0);
expect(resolve.userWork4).to.be.above(0);
});
beforeEach(function () {
routes = new RouteManager();
});
var SchedulingTest = function (opts) {
@ -56,28 +32,22 @@ define(function (require) {
var Private;
var Promise;
var $injector;
var $scope;
inject(function ($rootScope, _Private_, _Promise_, _$injector_) {
Private = _Private_;
Promise = _Promise_;
$injector = _$injector_;
$scope = $rootScope.$new();
});
stub(
Private(require('utils/routes/_setup')),
'routeSetupWork',
function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
setupComplete = true;
resolve();
$scope.$apply();
}, 50);
});
}
);
var setup = Private(require('utils/routes/_setup'));
stub(setup, 'routeSetupWork', function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
setupComplete = true;
resolve();
}, delaySetup);
});
});
routes
.when('/', {
@ -103,7 +73,6 @@ define(function (require) {
})
.then(resolve, reject);
$scope.$apply();
}, delayUserWork);
});
};