Browse Source

Support late callback binding for Promises

Listeners attached with addCallback / addErrback will now be executed
right away if the promise has already fired.
v0.7.4-release
Felix Geisendörfer 15 years ago
committed by Ryan Dahl
parent
commit
f64371fccb
  1. 2
      doc/api.txt
  2. 23
      src/node.js
  3. 50
      test/mjsunit/test-promise.js

2
doc/api.txt

@ -290,9 +290,11 @@ emit anymore events.
+promise.addCallback(listener)+ ::
Adds a listener for the +"success"+ event. Returns the same promise object.
The listener is executed right away if the promise has already fired.
+promise.addErrback(listener)+ ::
Adds a listener for the +"error"+ event. Returns the same promise object.
The listener is executed right away if the promise has already fired.
+promise.emitSuccess(arg1, arg2, ...)+ ::
If you created the promise (by doing +new events.Promise()+) then call

23
src/node.js

@ -232,6 +232,7 @@ var eventsModule = createInternalModule('events', function (exports) {
exports.EventEmitter.call();
this._blocking = false;
this.hasFired = false;
this._values = undefined;
};
process.inherits(exports.Promise, exports.EventEmitter);
@ -277,24 +278,34 @@ var eventsModule = createInternalModule('events', function (exports) {
exports.Promise.prototype.emitSuccess = function() {
if (this.hasFired) return;
this.hasFired = true;
Array.prototype.unshift.call(arguments, 'success')
this.emit.apply(this, arguments);
this._values = Array.prototype.slice.call(arguments);
this.emit.apply(this, ['success'].concat(this._values));
};
exports.Promise.prototype.emitError = function() {
if (this.hasFired) return;
this.hasFired = true;
Array.prototype.unshift.call(arguments, 'error')
this.emit.apply(this, arguments);
this._values = Array.prototype.slice.call(arguments);
this.emit.apply(this, ['error'].concat(this._values));
};
exports.Promise.prototype.addCallback = function (listener) {
this.addListener("success", listener);
if (!this.hasFired) {
return this.addListener("success", listener);
}
listener.apply(this, this._values);
return this;
};
exports.Promise.prototype.addErrback = function (listener) {
this.addListener("error", listener);
if (!this.hasFired) {
return this.addListener("error", listener);
}
listener.apply(this, this._values);
return this;
};

50
test/mjsunit/test-promise.js

@ -0,0 +1,50 @@
process.mixin(require('./common'));
var
Promise = require('events').Promise,
TEST_VALUE = {some: 'object'},
expectedCallbacks = {
a1: 1,
a2: 1,
b1: 1,
b2: 1,
};
// Test regular & late callback binding
var a = new Promise();
a.addCallback(function(value) {
assert.equal(TEST_VALUE, value);
expectedCallbacks.a1--;
});
a.emitSuccess(TEST_VALUE);
a.addCallback(function(value) {
assert.equal(TEST_VALUE, value);
expectedCallbacks.a2--;
});
// Test regular & late errback binding
var b = new Promise();
b.addErrback(function(value) {
assert.equal(TEST_VALUE, value);
expectedCallbacks.b1--;
});
b.emitError(TEST_VALUE);
b.addErrback(function(value) {
assert.equal(TEST_VALUE, value);
expectedCallbacks.b2--;
});
process.addListener('exit', function() {
for (var name in expectedCallbacks) {
var count = expectedCallbacks[name];
assert.equal(
0,
count,
'Callback '+name+' fire count off by: '+count
);
}
});
Loading…
Cancel
Save