Commit a79070b4 authored by Tristan Cavelier's avatar Tristan Cavelier

Add Promise progress

parent d6449937
...@@ -39,6 +39,11 @@ var Promise = function(resolver, canceller) { ...@@ -39,6 +39,11 @@ var Promise = function(resolver, canceller) {
reject(promise, value); reject(promise, value);
}; };
var notifyPromise = function(value) {
if (resolved) { return; }
notify(promise, value);
};
this.on('promise:failed', function(event) { this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
...@@ -62,7 +67,7 @@ var Promise = function(resolver, canceller) { ...@@ -62,7 +67,7 @@ var Promise = function(resolver, canceller) {
}; };
try { try {
resolver(resolvePromise, rejectPromise); resolver(resolvePromise, rejectPromise, notifyPromise);
} catch(e) { } catch(e) {
rejectPromise(e); rejectPromise(e);
} }
...@@ -104,6 +109,22 @@ var invokeCallback = function(type, promise, callback, event) { ...@@ -104,6 +109,22 @@ var invokeCallback = function(type, promise, callback, event) {
} }
}; };
var invokeNotifyCallback = function(promise, callback, event) {
var value;
if (typeof callback === 'function') {
try {
value = callback(event.detail);
} catch (e) {
// stop propagating
return;
}
notify(promise, value);
} else {
notify(promise, event.detail);
}
};
Promise.prototype = { Promise.prototype = {
constructor: Promise, constructor: Promise,
...@@ -112,7 +133,7 @@ Promise.prototype = { ...@@ -112,7 +133,7 @@ Promise.prototype = {
rejectedReason: undefined, rejectedReason: undefined,
fulfillmentValue: undefined, fulfillmentValue: undefined,
then: function(done, fail) { then: function(done, fail, progress) {
this.off('error', onerror); this.off('error', onerror);
var thenPromise = new this.constructor(function() {}, var thenPromise = new this.constructor(function() {},
...@@ -140,6 +161,10 @@ Promise.prototype = { ...@@ -140,6 +161,10 @@ Promise.prototype = {
invokeCallback('reject', thenPromise, fail, event); invokeCallback('reject', thenPromise, fail, event);
}); });
this.on('promise:notified', function (event) {
invokeNotifyCallback(thenPromise, progress, event);
});
return thenPromise; return thenPromise;
}, },
...@@ -221,4 +246,10 @@ function reject(promise, value) { ...@@ -221,4 +246,10 @@ function reject(promise, value) {
}); });
} }
function notify(promise, value) {
config.async(function() {
promise.trigger('promise:notified', { detail: value });
});
}
export { Promise }; export { Promise };
...@@ -178,6 +178,64 @@ describe("RSVP extensions", function() { ...@@ -178,6 +178,64 @@ describe("RSVP extensions", function() {
}); });
it('notify should exist', function (done) {
var exists, promise = new RSVP.Promise(function (resolve, reject, notify) {
exists = typeof notify === 'function';
});
setTimeout(function () {
assert(exists);
done();
}, 20);
});
it('should notify if `notify` is called with a value', function (done) {
var promise = new RSVP.Promise(function (resolve, reject, notify) {
notify('foo');
});
promise.then(null, null, function (foo) {
assert.equal(foo, 'foo');
done();
});
});
it('should notify twice before resolve', function (done) {
var notified = 0, promise = new RSVP.Promise(function (resolve, reject, notify) {
notify('foo');
notify('bar');
resolve('end');
notify('should not be notified');
});
promise.then(function () {
var currently_notified = notified;
setTimeout(function () {
assert.equal(currently_notified, 2);
assert.equal(notified, 2);
done();
}, 50);
}, null, function () {
notified += 1;
});
});
it('notify should propagate on two then', function (done) {
var last_notified = false, promise = new RSVP.Promise(function (resolve, reject, notify) {
notify('foo');
});
promise.then(null, null, function (foo) {
assert.equal(foo, 'foo');
return 'bar';
}).then(null, null, function (bar) {
assert.equal(bar, 'bar');
setTimeout(function () {
assert(!last_notified);
done();
}, 50);
throw 'baz';
}).then(null, null, function () {
last_notified = true;
});
});
describe('assimilation', function() { describe('assimilation', function() {
it('should assimilate if `resolve` is called with a fulfilled promise', function(done) { it('should assimilate if `resolve` is called with a fulfilled promise', function(done) {
var originalPromise = new RSVP.Promise(function(resolve) { resolve('original value'); }); var originalPromise = new RSVP.Promise(function(resolve) { resolve('original value'); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment