Skip to content

Instantly share code, notes, and snippets.

@mejedi
Created February 21, 2013 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mejedi/5004088 to your computer and use it in GitHub Desktop.
Save mejedi/5004088 to your computer and use it in GitHub Desktop.
Inertial: the state that doesn't change instantly. Inertial.set(value, cb, apply) — register intent to change the state to the value. Cb gets called as soon as the state was changed to the value *OR* when the operation failed *OR* when the state did change to another value due to completion of a more recent request. The later requires some clari…
function inertial(v) {
var self = this;
self.value = v;
var q = null;
self.set = function(value, cb, apply) {
if (!q && value == v) {
process.nextTick(function() {
safeCall(cb, null, value);
});
} else {
if (!q) {
process.nextTick(function() {
apply(cc);
});
}
q = {v:value, apply:apply, cb:cb, next:(q && !q.cb ? q.next : q)};
}
}
function cc(error, value) {
var i = q;
if (!error) {
self.value = v = value;
while (i && i.v != value) {
i = i.next;
}
} else {
while (i.next) {
i = i.next;
}
}
function invoke(i) {
if (i) {
invoke(i.next);
safeCall(i.cb, error, value);
}
}
invoke(i);
if (i==q) {
q = null;
} else {
var j = q;
while (j && j.next != i) {
j = j.next;
}
if (j) {
j.next = null;
}
q.apply(cc);
}
}
}
function safeCall(fn) {
if (fn && typeof fn == 'function') {
fn.apply(this, Array.prototype.slice.call(arguments, 1));
}
}
1 1
!2
2 2
!5
3 5
4 5
5 5
test = new inertial(1);
[1,2,3,4,5].forEach(function(v) {
test.set(v,
function(error, value) {
console.log(v, value);
},
function(cb) {
console.log('!'+v);
setTimeout(function() {
cb(null,v);
}, 1000);
}
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment