Commit 46330d04 authored by Romain Courteaud's avatar Romain Courteaud

Queue: add a thenable argument to resolve with a Queue

parent 29822afe
......@@ -12,7 +12,7 @@ function ResolvedQueueError(message) {
ResolvedQueueError.prototype = new Error();
ResolvedQueueError.prototype.constructor = ResolvedQueueError;
var Queue = function() {
var Queue = function(thenable) {
var queue = this,
promise_list = [],
promise,
......@@ -30,6 +30,26 @@ var Queue = function() {
}
}
function checkPromise(next_promise) {
promise_list.push(next_promise);
// Handle pop
promise_list.push(next_promise.then(function (fulfillmentValue) {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
fulfill(fulfillmentValue);
} else {
return fulfillmentValue;
}
}, function (rejectedReason) {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
reject(rejectedReason);
} else {
throw rejectedReason;
}
}));
}
promise = new Promise(function(done, fail) {
fulfill = function (fulfillmentValue) {
if (resolved) {return;}
......@@ -47,13 +67,7 @@ var Queue = function() {
};
}, canceller);
promise_list.push(resolve());
promise_list.push(promise_list[0].then(function () {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
fulfill();
}
}));
checkPromise(resolve(thenable));
queue.cancel = function () {
if (resolved) {return;}
......@@ -76,25 +90,9 @@ var Queue = function() {
throw new ResolvedQueueError();
}
next_promise = last_promise.then(done, fail);
promise_list.push(next_promise);
// Handle pop
promise_list.push(next_promise.then(function (fulfillmentValue) {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
fulfill(fulfillmentValue);
} else {
return fulfillmentValue;
}
}, function (rejectedReason) {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
reject(rejectedReason);
} else {
throw rejectedReason;
}
}));
checkPromise(last_promise.then(done, fail));
return this;
};
......
......@@ -2147,9 +2147,9 @@ describe("`RSVP.Queue`", function () {
});
describe("`Queue` constructor", function () {
it('should exist and have length 0', function () {
it('should exist and have length 1', function () {
assert(RSVP.Queue);
assert.equal(RSVP.Queue.length, 0);
assert.equal(RSVP.Queue.length, 1);
});
it('should be a constructor', function () {
......@@ -2240,6 +2240,37 @@ describe("`RSVP.Queue`", function () {
setTimeout(function() {
assert.equal(queue.isFulfilled, true);
assert.equal(queue.fulfillmentValue, undefined);
done();
}, 20);
});
it('should be fulfilled with the static argument', function (done) {
var queue = new RSVP.Queue('foo');
setTimeout(function() {
assert.equal(queue.isFulfilled, true);
assert.equal(queue.fulfillmentValue, 'foo');
done();
}, 20);
});
it('should be fulfilled with the thenable argument', function (done) {
var queue = new RSVP.Queue(RSVP.resolve('bar'));
setTimeout(function() {
assert.equal(queue.isFulfilled, true);
assert.equal(queue.fulfillmentValue, 'bar');
done();
}, 20);
});
it('should be rejected with the rejected thenable argument', function (done) {
var queue = new RSVP.Queue(RSVP.reject('ko'));
setTimeout(function() {
assert.equal(queue.isRejected, true);
assert.equal(queue.rejectedReason, 'ko');
done();
}, 20);
});
......@@ -2272,6 +2303,22 @@ describe("`RSVP.Queue`", function () {
}, 20);
});
it('`thenable` value is propagated to the next entry', function (done) {
var queue = new RSVP.Queue(RSVP.resolve('foo')),
pushed_result;
queue.push(function (value) {
pushed_result = value;
return "bar";
});
setTimeout(function() {
assert.equal(pushed_result, "foo");
assert.equal(queue.isFulfilled, true);
assert.equal(queue.fulfillmentValue, "bar");
done();
}, 20);
});
it('resolve value is propagated to the next entry', function (done) {
var queue = new RSVP.Queue(),
pushed_result;
......@@ -2319,7 +2366,23 @@ describe("`RSVP.Queue`", function () {
}, 20);
});
it('reject cancels the remaining promise', function (done) {
it('`thenable` rejection is propagated to the next entry', function (done) {
var queue = new RSVP.Queue(RSVP.timeout(1)),
pushed_result;
queue.push(undefined, function (value) {
pushed_result = value;
throw 'bar';
});
setTimeout(function() {
assert.equal(pushed_result, "Timed out after 1 ms");
assert.equal(queue.isRejected, true);
assert.equal(queue.rejectedReason, "bar");
done();
}, 20);
});
it('rejection is propagated to the next entry', function (done) {
var queue = new RSVP.Queue(),
pushed_result;
queue.push(function () {
......@@ -2327,13 +2390,13 @@ describe("`RSVP.Queue`", function () {
});
queue.push(undefined, function (value) {
pushed_result = value;
throw value;
throw 'bar';
});
setTimeout(function() {
assert.equal(pushed_result, "Timed out after 1 ms");
assert.equal(queue.isRejected, true);
assert.equal(queue.rejectedReason, "Timed out after 1 ms");
assert.equal(queue.rejectedReason, "bar");
done();
}, 20);
});
......@@ -2413,6 +2476,52 @@ describe("`RSVP.Queue`", function () {
}, 20);
});
it('should `cancel` default `thenable`', function (done) {
var thenable_cancel_called = false,
thenable_ongoing = false,
later_success_thenable_called = false,
later_error_thenable_called = false,
queue = new RSVP.Queue(new RSVP.Promise(
function () {
thenable_ongoing = true;
},
function () {
thenable_cancel_called = true;
})
)
.push(
// Should be skipped
function () {later_success_thenable_called = true;},
function () {later_error_thenable_called = true;}
),
result = 'MARKER1',
error = 'MARKER2';
queue.then(function(e) {
result = e;
});
queue.fail(function(e) {
error = e;
});
setTimeout(function() {
assert.equal(queue.isRejected, undefined);
assert.equal(queue.isFulfilled, undefined);
assert.equal(thenable_ongoing, true);
queue.cancel();
assert.equal(thenable_cancel_called, true);
setTimeout(function() {
assert.equal(queue.isRejected, true);
assert.equal(queue.isFulfilled, undefined);
assert(queue.rejectedReason instanceof RSVP.CancellationError);
assert.equal(result, 'MARKER1');
assert(error instanceof RSVP.CancellationError);
assert.equal(later_success_thenable_called, false);
assert.equal(later_error_thenable_called, false);
done();
}, 20);
}, 20);
});
it('should `cancel` pending success `thenable`', function (done) {
var thenable_cancel_called = false,
thenable_ongoing = false,
......
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