Skip to content
Browse files

The return of Promise.cancel() with some additional tests & docs

  • Loading branch information...
1 parent 7b2fdc0 commit 659954d842acad282cf03850e09c702da0d0f381 @felixge felixge committed with ry
Showing with 98 additions and 1 deletion.
  1. +16 −1 doc/api.txt
  2. +33 −0 src/events.js
  3. +49 −0 test/mjsunit/test-promise-timeout.js
View
17 doc/api.txt
@@ -215,6 +215,7 @@ emit anymore events.
| Event | Parameters | Notes
| +"success"+ | (depends) |
| +"error"+ | (depends) |
+| +"cancel"+ | (depends) |
|=========================================================
+promise.addCallback(listener)+ ::
@@ -223,6 +224,9 @@ Adds a listener for the +"success"+ event. Returns the same promise object.
+promise.addErrback(listener)+ ::
Adds a listener for the +"error"+ event. Returns the same promise object.
++promise.addCancelback(listener)+ ::
+Adds a listener for the +"cancel"+ event. Returns the same promise object.
+
+promise.emitSuccess(arg1, arg2, ...)+ ::
If you created the promise (by doing +new node.Promise()+) then call
+emitSuccess+ to emit the +"success"+ event with the given arguments.
@@ -233,10 +237,21 @@ the moment due to a bug; use +emitSuccess+ instead.)
+promise.emitError(arg1, arg2, ...)+ ::
Emits the +"error"+ event.
++promise.emitCancel(arg1, arg2, ...)+ ::
+Emits the +"cancel"+ event. You may still get a +"success"+ or +"error"+
+callback if the promise giver does not handle the cancel event. Use
++promise.cancel()+ to ignore any later events.
+
++promise.cancel()+ ::
+Clears all +"success"+ and +"error"+ event listeners from the promise, then
+emits the +"cancel"+ event. Whether or not the promise is actually canceled
+or not depends on the promise giver. This also clears Promise.timeout() if one
+was set.
+
+promise.timeout(timeout = undefined)+ ::
If the +timeout+ parameter is provided, the promise will emit an +"error"+
event after the given amount of millseconds. The timeout is canceled by any
-+"success"+ or +"error"+ event being emitted by the Promise.
++"success"+, +"error"+ or +"cancel"+ event being emitted by the Promise.
+
To tell apart a timeout from a regular "error" event, use the following test:
+
View
33 src/events.js
@@ -30,14 +30,42 @@ node.Promise.prototype.timeout = function(timeout) {
clearTimeout(this._timer);
}
+ var promiseComplete = false;
+ var onComplete = function() {
+ promiseComplete = true;
+ };
+
+ this
+ .addCallback(onComplete)
+ .addCancelback(onComplete)
+ .addErrback(onComplete);
+
var self = this
this._timer = setTimeout(function() {
+ if (promiseComplete) {
+ return;
+ }
+
self.emitError(new Error('timeout'));
}, this._timeoutDuration);
return this;
};
+node.Promise.prototype.cancel = function() {
+ this._events['success'] = [];
+ this._events['error'] = [];
+
+ this.emitCancel();
+};
+
+node.Promise.prototype.emitCancel = function() {
+ var args = Array.prototype.slice.call(arguments);
+ args.unshift('cancel');
+
+ this.emit.apply(this, args);
+};
+
node.Promise.prototype.addCallback = function (listener) {
this.addListener("success", listener);
return this;
@@ -48,6 +76,11 @@ node.Promise.prototype.addErrback = function (listener) {
return this;
};
+node.Promise.prototype.addCancelback = function (listener) {
+ this.addListener("cancel", listener);
+ return this;
+};
+
node.Promise.prototype.wait = function () {
var ret;
var had_error = false;
View
49 test/mjsunit/test-promise-timeout.js
@@ -29,6 +29,55 @@ try {
timeouts++;
}
+var successPromise = new node.Promise();
+successPromise.timeout(500);
+setTimeout(function() {
+ successPromise.emitSuccess();
+}, 250);
+
+successPromise.addErrback(function() {
+ assertUnreachable('addErrback should not fire if there is no timeout');
+});
+
+var errorPromise = new node.Promise();
+errorPromise.timeout(500);
+setTimeout(function() {
+ errorPromise.emitError(new Error('intentional'));
+}, 250);
+
+errorPromise.addErrback(function(e) {
+ assertInstanceof(e, Error);
+ assertEquals('intentional', e.message);
+});
+
+var cancelPromise = new node.Promise();
+cancelPromise.timeout(500);
+setTimeout(function() {
+ cancelPromise.cancel();
+}, 250);
+
+setTimeout(function() {
+ cancelPromise.emitSuccess('should be ignored');
+}, 400);
+
+cancelPromise.addCallback(function(e) {
+ assertUnreachable('addCallback should not fire if the promise is canceled');
+});
+
+cancelPromise.addErrback(function(e) {
+ assertUnreachable('addErrback should not fire if the promise is canceled');
+});
+
+var cancelTimeoutPromise = new node.Promise();
+cancelTimeoutPromise.timeout(500);
+setTimeout(function() {
+ cancelPromise.emitCancel();
+}, 250);
+
+cancelPromise.addErrback(function(e) {
+ assertUnreachable('addErrback should not fire after a cancel event');
+});
+
process.addListener('exit', function() {
assertEquals(2, timeouts);
});

0 comments on commit 659954d

Please sign in to comment.
Something went wrong with that request. Please try again.