MilestoneJS
This is a library of asynchronous flow control, which is based on Promises/A.
This library can express asynchronous processing more nearly intuitively. And processing can be made to hook more flexibly by including EventEmitter further compared with general Promises/A library.
Table of contents
Usage
in Node.js
install MilestoneJS with github npm install milestonejs
, then require it as below.
var Milestone = require('milestonejs').Milestone;
, milestone = new Milestone()
;
in HTML
load MilestoneJS as a script <script type="text/javascript" src="/path/to/milestone-csjs.js"></script>
, then require it as below.
var milestone = new milestoneJS.Milestone();
Then, write your module with milestone
.
var milestoneJS = require('milestonejs')
, Milestone = milestoneJS.Milestone
, mission
, mission2
;
function countTenSecond() {
var milestone = new Milestone()
;
(function a(idx) {
var baseCamp;
if (idx === 10) {
milestone.complete(idx);
return;
} else {
baseCamp = 'baseCamp' + idx;
milestone.comeAt(baseCamp, idx);
}
setTimeout(function () {
a(++idx);
}, 1000);
}(0));
return milestone.mission;
}
mission = countTenSecond();
mission.on('baseCamp1', function (idx) {
console.log('1 second passed');
});
mission.on('baseCamp2', function (idx) {
console.log('2 second passed');
});
mission.complete(function (time) {
console.log('10 second passed');
});
mission2 = countTenSecond();
milestoneJS.when({
a: mission,
b: mission2
}).complete(function (res) {
console.log(res.a);
console.log(res.b);
});
The API
Here is the whole API
Milestone Object / Mission Object
Instance of Milestone can be obtained as follows.
var milestoneJS = require('milestonejs')
, milestone = new milestoneJS.Milestone()
;
By using milestoneJS, function returns mission object
, without waiting for the delayed processing.
Moreover, bind of the processing can be carried out by registering callback into mission object
at the time of completion of delay processing.
function delay() {
var milestone = new milestoneJS.Milestone()
;
setTimeout(function () {
milestone.complete('done');
}, 100);
return milestone.mission;
}
delay().complete(function (msg) {
console.log(msg); // output 'done'
});
Moreover, not only the state of completion but its process can also be notified.
function delay() {
var milestone = new milestoneJS.Milestone()
;
setTimeout(function () {
milestone.comeAt('herf', '50msec ago');
setTimeout(function () {
milestone.complete('done');
}, 50);
}, 50);
return milestone.mission;
}
delay().on('herf', function (msg) {
console.log(msg); // output '50msec ago'
}).complete(function (msg) {
console.log(msg); // output 'done'
});
Of course, failure in processing is also detectable.
function delay() {
var milestone = new milestoneJS.Milestone()
;
setTimeout(function () {
try {
new Error('fuckin');
} catch(err) {
milestone.reject(err);
}
}, 50);
return milestone.mission;
}
delay().fail(function (err) {
console.log(err.message); // output 'fuckin'
});
then
is used to define the processing at the time of a success and failure simultaneously.
arg1: success callback
arg2: fail callback
function delay() {
var milestone = new milestoneJS.Milestone()
;
setTimeout(function () {
try {
if (+new Date % 2 === 0) {
milestone.complete('done')
} else {
throw new Error('fuckin');
}
} catch(err) {
milestone.reject(err);
}
}, 50);
return milestone.mission;
}
// arg1 callback will be performed if it succeeds.
// However, arg2 callback will be performed if it has failed.
delay().then(function (msg) {
console.log(msg); // output 'done'
}, function (err) {
console.log(err.message); // output 'fuckin'
});
You might want to use mission.finish()
if you want to execute when processing regardless of success or failure, mission
is finished.
var milestone = new milestoneJS.Milestone()
, mission = milestone.mission
;
setTimeout(function () {
if (+new Date % 2 === 0) {
milestone.complete('done');
} else {
milestone.reject('oops');
}
}, 1);
mission.finish(function (msg) {
console.log(msg); // output 'done' or 'oops'
});
Branch of processing according to the state of mission
is attained by using mission.isCompleted()
and mission.isRejected()
.
var milestone = new milestoneJS.Milestone()
, mission = milestone.mission
, assert = require('assert')
;
milestone.completed('done');
assert.ok(mission.isCompleted()); // pass
assert.fail(mission.isRejected()); // pass
when method
when
will be used if processing is related with the end status of two or more mission
.
By using when
, two or more mission
can be treated just like one mission
.
function delay() {
var milestone = new milestoneJS.Milestone()
;
setTimeout(function () {
mission.complete('done');
}, 50);
return milestone.mission;
}
var mission1 = delay();
var mission2 = delay();
milestoneJS.when({
a: mission1,
b: mission2
}).complete(function (res) {
console.log(res.a); // output 'done'
console.log(res.b); // output 'done'
}).fail(function (err) {
console.log(err);
});
In addition, you can use an Mission.createBaseCamp()
also offers state management of multiple Mission
as well as the state management of multiple milestone
.
Mission.createBaseCamp()
returns a new Mission
that is completed at the timing of the Mission.comeAt('...')
.
function delay() {
var milestone = new milestoneJS.Milestone()
;
setTimeout(function (timer) {
milestone.comeAt('herf', 'Half the time has elapsed.');
setTimeout(function () {
milestone.complete('done');
}, timer / 2);
}, timer / 2);
return milestone.mission;
}
var mission1 = delay(200);
var mission2 = delay(300);
milestoneJS.when({
a: mission1.createBaseCamp('herf'),
b: mission2
}).complete(function (res) {
console.log(res.a); // output 'Half the time has elapsed.'
console.log(res.b); // output 'done'
});