Refactoring queues to look more like queues
MODIFY
addon/services/scheduler.js
addon/services/scheduler.js
import Ember from 'ember';
import { DEBUG } from '@glimmer/env';
+import Token from '../token';
+import TaskQueue from '../task-queue';
const {
run,
@@ -7,33 +9,6 @@ const {
Service,
} = Ember;
-class Token {
- constructor() {
- this._cancelled = false;
- }
-
- get cancelled() {
- return this._cancelled;
- }
-
- cancel() {
- this._cancelled = true;
- }
-}
-
-class Queue {
- constructor() {
- this.reset();
- }
-
- reset() {
- this.tasks = [];
- this.isActive = true;
- this.afterPaintDeferred = RSVP.defer();
- this.afterPaintPromise = this.afterPaintDeferred.promise;
- }
-}
-
const Scheduler = Service.extend({
queueNames: ['afterFirstRoutePaint', 'afterContentPaint'],
@@ -54,8 +29,7 @@ const Scheduler = Service.extend({
const token = new Token();
if (queue.isActive) {
- queue.tasks.push(callback);
- queue.tasks.push(token);
+ queue.enqueue({token, callback});
} else {
callback();
}
@@ -71,12 +45,11 @@ const Scheduler = Service.extend({
const queue = this.queues[queueName];
queue.isActive = false;
- for (let i = 0; i < queue.tasks.length; i += 2) {
- const callback = queue.tasks[i];
- const token = queue.tasks[i+1];
+ while (queue.tasks.length) {
+ const task = queue.dequeue();
- if (!token.cancelled) {
- callback();
+ if (!task.token.cancelled) {
+ task.callback();
}
}
@@ -91,7 +64,7 @@ const Scheduler = Service.extend({
const queueNames = this.queueNames;
for (let i = 0; i < queueNames.length; i++) {
- queues[queueNames[i]] = new Queue();
+ queues[queueNames[i]] = new TaskQueue();
}
},

ADD
addon/task-queue.js
+import RSVP from 'rsvp';
+
+export default class TaskQueue {
+ constructor() {
+ this.reset();
+ }
+
+ enqueue(task) {
+ this.tasks.push(task);
+ }
+
+ dequeue() {
+ return this.tasks.shift();
+ }
+
+ size() {
+ return this.tasks.length;
+ }
+
+ reset() {
+ this.tasks = [];
+ this.isActive = true;
+ this.afterPaintDeferred = RSVP.defer();
+ this.afterPaintPromise = this.afterPaintDeferred.promise;
+ }
+}
\ No newline at end of file

ADD
addon/token.js
+
+export default class Token {
+ constructor() {
+ this._cancelled = false;
+ }
+
+ get cancelled() {
+ return this._cancelled;
+ }
+
+ cancel() {
+ this._cancelled = true;
+ }
+ }
\ No newline at end of file

MODIFY
testem.js
testem.js
@@ -8,12 +8,15 @@ module.exports = {
launch_in_dev: [
'Chrome'
],
- browser_args: {
- Chrome: [
+ 'browser_args': {
+ Chrome: {
+ mode: 'ci',
+ args: [
'--disable-gpu',
'--headless',
'--remote-debugging-port=9222',
'--window-size=1440,900'
]
+ },
}
};

ADD
tests/unit/task-queue-test.js
+import { module, test } from 'qunit';
+import TaskQueue from 'ember-app-scheduler/task-queue';
+import Token from 'ember-app-scheduler/token';
+
+module(`Unit | ember-app-scheduler | Queue`, {
+ beforeEach() {
+ this.taskQueue = new TaskQueue();
+
+ this.createTask = () => {
+ return { token: new Token(), callback: () => {} };
+ }
+ }
+});
+
+test('queue size is 0 when instantiated', function(assert) {
+ assert.expect(1);
+
+ assert.equal(this.taskQueue.size(), 0, 'size is 0');
+});
+
+test('queue size is 1 when item is enqueued', function(assert) {
+ assert.expect(1);
+
+ this.taskQueue.enqueue(this.createTask());
+
+ assert.equal(this.taskQueue.size(), 1, 'size is 1');
+});
+
+test('task is enqueued', function(assert) {
+ assert.expect(1);
+
+ const task = this.createTask();
+
+ this.taskQueue.enqueue(task);
+
+ assert.equal(task, this.taskQueue.tasks[0], 'task is correctly enqueued');
+});
+
+test('task is dequeued', function(assert) {
+ assert.expect(1);
+
+ const task = this.createTask();
+
+ this.taskQueue.enqueue(task);
+
+ const expectedTask = this.taskQueue.dequeue();
+
+ assert.equal(task, expectedTask, 'task is correctly dequeued');
+});
+
+test('task is dequeued in the correct order', function(assert) {
+ assert.expect(1);
+
+ const firstTask = this.createTask();
+ const secondTask = this.createTask();
+
+ this.taskQueue.enqueue(firstTask);
+ this.taskQueue.enqueue(secondTask);
+
+ const expectedTask = this.taskQueue.dequeue();
+
+ assert.equal(firstTask, expectedTask, 'task is correctly dequeued');
+});
+
+test('queue is reset correctly', function(assert) {
+ assert.expect(2);
+
+ const firstTask = this.createTask();
+ const secondTask = this.createTask();
+
+ this.taskQueue.enqueue(firstTask);
+ this.taskQueue.enqueue(secondTask);
+
+ this.taskQueue.reset();
+
+ assert.equal(this.taskQueue.size(), 0, 'size is 0');
+ assert.ok(this.taskQueue.isActive, 'size is 0');
+});

ADD
tests/unit/token-test.js
tests/unit/token-test.js
Refactoring queues to look more like queues