-
-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merged promise files and history from TryGhost/Ghost
* extracted promise lib files and tests from Ghost * includes commits: Updated var declarations to const/let and no lists Move tests from core to root (#11700) Extended sequence utility Moved pipeline/sequence to lib/promise
- Loading branch information
Showing
4 changed files
with
185 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* # Pipeline Utility | ||
* | ||
* Based on pipeline.js from when.js: | ||
* https://github.com/cujojs/when/blob/3.7.4/pipeline.js | ||
*/ | ||
const Promise = require('bluebird'); | ||
|
||
function pipeline(tasks /* initial arguments */) { | ||
const args = Array.prototype.slice.call(arguments, 1); | ||
|
||
let runTask = function (task, args) { | ||
// Self-optimizing function to run first task with multiple | ||
// args using apply, but subsequent tasks via direct invocation | ||
runTask = function (task, arg) { | ||
return task(arg); | ||
}; | ||
|
||
return task.apply(null, args); | ||
}; | ||
|
||
// Resolve any promises for the arguments passed in first | ||
return Promise.all(args).then(function (args) { | ||
// Iterate through the tasks passing args from one into the next | ||
return Promise.reduce(tasks, function (arg, task) { | ||
return runTask(task, arg); | ||
}, args); | ||
}); | ||
} | ||
|
||
module.exports = pipeline; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
const Promise = require('bluebird'); | ||
|
||
/** | ||
* expects an array of functions returning a promise | ||
*/ | ||
function sequence(tasks /* Any Arguments */) { | ||
const args = Array.prototype.slice.call(arguments, 1); | ||
|
||
return Promise.reduce(tasks, function (results, task) { | ||
const response = task.apply(this, args); | ||
|
||
if (response && response.then) { | ||
return response.then(function (result) { | ||
results.push(result); | ||
return results; | ||
}); | ||
} else { | ||
return Promise.resolve().then(() => { | ||
results.push(response); | ||
return results; | ||
}); | ||
} | ||
}, []); | ||
} | ||
|
||
module.exports = sequence; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
const should = require('should'); | ||
const sinon = require('sinon'); | ||
const Promise = require('bluebird'); | ||
|
||
// Stuff we are testing | ||
const pipeline = require('../../../../core/server/lib/promise/pipeline'); | ||
|
||
// These tests are based on the tests in https://github.com/cujojs/when/blob/3.7.4/test/pipeline-test.js | ||
function createTask(y) { | ||
return function (x) { | ||
return x + y; | ||
}; | ||
} | ||
|
||
describe('Pipeline', function () { | ||
afterEach(function () { | ||
sinon.restore(); | ||
}); | ||
|
||
it('should execute tasks in order', function () { | ||
return pipeline([createTask('b'), createTask('c'), createTask('d')], 'a').then(function (result) { | ||
result.should.eql('abcd'); | ||
}); | ||
}); | ||
|
||
it('should resolve to initial args when no tasks supplied', function () { | ||
return pipeline([], 'a', 'b').then(function (result) { | ||
result.should.eql(['a', 'b']); | ||
}); | ||
}); | ||
|
||
it('should resolve to empty array when no tasks and no args supplied', function () { | ||
return pipeline([]).then(function (result) { | ||
result.should.eql([]); | ||
}); | ||
}); | ||
|
||
it('should pass args to initial task', function () { | ||
const expected = [1, 2, 3]; | ||
const tasks = [sinon.spy()]; | ||
|
||
return pipeline(tasks, 1, 2, 3).then(function () { | ||
tasks[0].calledOnce.should.be.true(); | ||
tasks[0].firstCall.args.should.eql(expected); | ||
}); | ||
}); | ||
|
||
it('should allow initial args to be promises', function () { | ||
const expected = [1, 2, 3]; | ||
const tasks = [sinon.spy()]; | ||
const Resolver = Promise.resolve; | ||
|
||
return pipeline(tasks, new Resolver(1), new Resolver(2), new Resolver(3)).then(function () { | ||
tasks[0].calledOnce.should.be.true(); | ||
tasks[0].firstCall.args.should.eql(expected); | ||
}); | ||
}); | ||
|
||
it('should allow tasks to be promises', function () { | ||
const expected = [1, 2, 3]; | ||
|
||
const tasks = [ | ||
sinon.stub().returns(new Promise.resolve(4)), | ||
sinon.stub().returns(new Promise.resolve(5)), | ||
sinon.stub().returns(new Promise.resolve(6)) | ||
]; | ||
|
||
return pipeline(tasks, 1, 2, 3).then(function (result) { | ||
result.should.eql(6); | ||
tasks[0].calledOnce.should.be.true(); | ||
tasks[0].firstCall.args.should.eql(expected); | ||
tasks[1].calledOnce.should.be.true(); | ||
tasks[1].firstCall.calledWith(4).should.be.true(); | ||
tasks[2].calledOnce.should.be.true(); | ||
tasks[2].firstCall.calledWith(5).should.be.true(); | ||
}); | ||
}); | ||
|
||
it('should allow tasks and args to be promises', function () { | ||
const expected = [1, 2, 3]; | ||
|
||
const tasks = [ | ||
sinon.stub().returns(new Promise.resolve(4)), | ||
sinon.stub().returns(new Promise.resolve(5)), | ||
sinon.stub().returns(new Promise.resolve(6)) | ||
]; | ||
|
||
const Resolver = Promise.resolve; | ||
|
||
return pipeline(tasks, new Resolver(1), new Resolver(2), new Resolver(3)).then(function (result) { | ||
result.should.eql(6); | ||
tasks[0].calledOnce.should.be.true(); | ||
tasks[0].firstCall.args.should.eql(expected); | ||
tasks[1].calledOnce.should.be.true(); | ||
tasks[1].firstCall.calledWith(4).should.be.true(); | ||
tasks[2].calledOnce.should.be.true(); | ||
tasks[2].firstCall.calledWith(5).should.be.true(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const should = require('should'); | ||
const sinon = require('sinon'); | ||
const Promise = require('bluebird'); | ||
const sequence = require('../../../../core/server/lib/promise/sequence'); | ||
|
||
describe('Unit: lib/promise/sequence', function () { | ||
afterEach(function () { | ||
sinon.restore(); | ||
}); | ||
|
||
it('mixed tasks: promise and none promise', function () { | ||
const tasks = [ | ||
function a() { | ||
return Promise.resolve('hello'); | ||
}, | ||
function b() { | ||
return 'from'; | ||
}, | ||
function c() { | ||
return Promise.resolve('chio'); | ||
} | ||
]; | ||
return sequence(tasks) | ||
.then(function (result) { | ||
result.should.eql(['hello','from', 'chio']); | ||
}); | ||
}); | ||
}); |