Browse Source

optimize Sequence for performance by using Promise.each

Previously, Sequence was checking for Promise-type result
every time, to detect when a Promise needs to be returned
from .run() method, which created a deep Promise chain.

After this change, when Sequence finds Promise-type result
it uses Promise.each on all the remaining tests.
babel-plugin-for-integration-tests
vdemedes 9 years ago
parent
commit
ce1b0348a6
  1. 58
      lib/sequence.js

58
lib/sequence.js

@ -1,5 +1,8 @@
'use strict'; 'use strict';
var isPromise = require('is-promise'); var isPromise = require('is-promise');
var AvaError = require('./ava-error');
function noop() {}
module.exports = Sequence; module.exports = Sequence;
@ -17,21 +20,17 @@ function Sequence(tests, bail) {
this.reason = null; this.reason = null;
this.tests = tests; this.tests = tests;
this.bail = bail || false; this.bail = bail || false;
// TODO(vdemedes): separate into a utility (it's being used in serveral places)
Object.keys(Sequence.prototype).forEach(function (key) {
this[key] = this[key].bind(this);
}, this);
} }
Sequence.prototype.run = function () { Sequence.prototype.run = function () {
return this._run();
};
// run sequence items starting from specified index
Sequence.prototype._run = function (fromIndex) {
var length = this.tests.length; var length = this.tests.length;
if (!fromIndex) { for (var i = 0; i < length; i++) {
fromIndex = 0;
}
for (var i = fromIndex; i < length; i++) {
// if last item failed and we should bail, return results and stop // if last item failed and we should bail, return results and stop
if (this.bail && !this.passed) { if (this.bail && !this.passed) {
return this._results(); return this._results();
@ -39,26 +38,41 @@ Sequence.prototype._run = function (fromIndex) {
var result = this.tests[i].run(); var result = this.tests[i].run();
// if a Promise returned, we don't need to check for Promises after this test
// so we can just use Promise.each() on the rest of the tests
if (isPromise(result)) { if (isPromise(result)) {
return this._awaitResult(result, i + 1); return result
.then(this._addResult)
.return(this.tests.slice(i + 1))
.each(this._runTest)
.catch(AvaError, noop)
.then(this._results);
} }
try {
this._addResult(result); this._addResult(result);
} catch (err) {
// in bail mode, don't execute the next tests
if (err instanceof AvaError) {
return this._results();
}
throw err;
}
} }
return this._results(); return this._results();
}; };
// if result is a Promise, return it to make Sequence thennable Sequence.prototype._runTest = function (test) {
// add resolved result and continue execution from the next item var result = test.run();
Sequence.prototype._awaitResult = function (result, nextIndex) {
var self = this;
return result.then(function (ret) { if (isPromise(result)) {
self._addResult(ret); return result
.then(this._addResult);
}
return self._run(nextIndex); return this._addResult(result);
});
}; };
Sequence.prototype._addResult = function (result) { Sequence.prototype._addResult = function (result) {
@ -71,7 +85,13 @@ Sequence.prototype._addResult = function (result) {
if (!this.reason) { if (!this.reason) {
this.reason = result.reason; this.reason = result.reason;
} }
if (this.bail) {
throw new AvaError('Error in Sequence while in bail mode');
}
} }
return result;
}; };
Sequence.prototype._results = function () { Sequence.prototype._results = function () {

Loading…
Cancel
Save