Simplify `app.defineMiddlewarePhases`

Refactor the implementation to use the new method `phaseList.zipMerge`.

This is commit is changing the behaviour in the case when
the first new phase does not exist in the current list.

Before the change, all new phases were added just before the "routes"
phase.

After this change, new phases are added to the head of the list,
until an existing phase is encountered, at which point the regular
merge algorithm kicks in.

Example:

    app.defineMiddlewarePhases(['first', 'routes', 'subapps']);

Before the change: code throws an error - 'routes' already exists.

After the change: phases are merged with the following result:

    'first', 'initial', ..., 'routes', 'subapps', ...
This commit is contained in:
Miroslav Bajtoš 2014-11-12 08:59:56 +01:00
parent 4474f8b029
commit ae7d99682b
2 changed files with 12 additions and 40 deletions

View File

@ -84,44 +84,11 @@ proto.middlewareFromConfig = function(factory, config) {
*/
proto.defineMiddlewarePhases = function(nameOrArray) {
this.lazyrouter();
if (!Array.isArray(nameOrArray)) {
if (Array.isArray(nameOrArray)) {
this._requestHandlingPhases.zipMerge(nameOrArray);
} else {
this._requestHandlingPhases.addBefore('routes', nameOrArray);
return;
}
var sourcePhases = nameOrArray;
if (!sourcePhases.length) return;
var targetPhases = this._requestHandlingPhases.getPhaseNames();
var targetIx = targetPhases.indexOf(nameOrArray[0]);
if (targetIx === -1) {
// the first new phase does not match any existing one
// add all phases before "routes"
sourcePhases.forEach(function(it) {
this._requestHandlingPhases.addBefore('routes', it);
}, this);
return;
}
// merge (zip) two arrays of phases
for (var sourceIx = 1; sourceIx < sourcePhases.length; sourceIx++) {
var nameToAdd = sourcePhases[sourceIx];
var previousPhase = sourcePhases[sourceIx - 1];
var existingIx = targetPhases.indexOf(nameToAdd, targetIx);
if (existingIx === -1) {
// A new phase - try to add it after the last one,
// unless it was already registered
if (targetPhases.indexOf(nameToAdd) !== -1) {
throw new Error('Phase ordering conflict: cannot add "' + nameToAdd +
'" after "' + previousPhase + '", because the opposite order was ' +
' already specified');
}
this._requestHandlingPhases.addAfter(previousPhase, nameToAdd);
} else {
// An existing phase - move the pointer
targetIx = existingIx;
}
}
};

View File

@ -157,9 +157,14 @@ describe('app', function() {
verifyMiddlewarePhases(['custom', 'routes'], done);
});
it('adds an array of phases just before "routes"', function(done) {
app.defineMiddlewarePhases(['custom1', 'custom2']);
verifyMiddlewarePhases(['custom1', 'custom2', 'routes'], done);
it('merges phases adding to the start of the list', function(done) {
app.defineMiddlewarePhases(['first', 'routes', 'subapps']);
verifyMiddlewarePhases([
'first',
'initial', // this was the original first phase
'routes',
'subapps'
], done);
});
it('merges phases preserving the order', function(done) {