I'm an Ember newbie, so forgive me if I've missed something obvious (I've spent time Googling this issue and still can't find a solution) but it seems to me that Ember computed properties aren't working as documented/intended on array properties like length.
I'm trying to build my own queue:
// app/custom-objects/processing-queue-item.js
import Ember from 'ember';
export default Ember.Object.extend({
payload: null,
extraContext: null,
processingState: 'pending', // pending, succeeded, failed
processingOutcome: null, // null for pending, result for succeeded, error for failed
toString() {
return `{ProcessingQueueItem: processingState=${this.get('processingState')}, processingOutcome=${this.get('processingOutcome')}, extraContext=${this.get('extraContext')}, payload=${this.get('payload')}}`;
}
});
// app/custom-objects/processing-queue.js
import Ember from 'ember';
import ProcessingQueueItem from './processing-queue-item';
export default Ember.Object.extend(Ember.Enumerable, {
queueName: null,
init() {
this.set('items', []);
this.get('items');
this.get('items.length');
this.get('length'); // Force observation
},
/*
* Public API
*/
enqueue(payload, extraContext = null) {
let itemToEnqueue = ProcessingQueueItem.create({ payload: payload, extraContext: extraContext });
this.get('items').pushObject(itemToEnqueue);
this.scheduleProcessing();
return itemToEnqueue;
},
toString() {
return `{ProcessingQueue: queueName=${this.get('queueName')}, length=${this.get('length')}}`;
},
/*
* Internal API
*/
scheduleProcessing() {
Ember.run(() => {
this.maybeProcessAnItem();
});
},
maybeProcessAnItem() {
console.log(`maybe process an item ${this}`);
},
/*
* Ember.Enumerable mixin
*/
length: Ember.computed('items.length', function() {
return this.get('items.length');
}),
nextObject(index, previousObject, context) {
return this.get('items').nextObject(index, previousObject, context);
}
});
This class is incomplete, but I want to start displaying queue contents in a template to help with debugging but I can't get that to work. Here are my controller and template:
// app/controllers/dashboard.js
import Ember from 'ember';
import ProcessingQueue from '../custom-objects/processing-queue';
export default Ember.Controller.extend({
init() {
this._super(...arguments);
this.set('processingQueue', ProcessingQueue.create({ queueName: 'DashboardQueue' }));
this.get('processingQueue');
this.get('processingQueue.length');
this.get('queueLength');
},
queueLength: Ember.computed('processingQueue.length', function() {
return this.get('processingQueue.length');
}),
});
// app/templates/dashboard.hbs
<h1>Dashboard</h1>
<h2>Queue Length: ''</h2>
<p></p>
The problem is, in the <h2>Queue Length: ''</h2>
, the queue length is always undefined until I add items to the queue. But this is not true, the queue has an empty array and a length of 0. Using $E
from the dashboard controller from EmberInspector I can see that $E.get('processingQueue.length')
and $E.get('queueLength')
are both undefined
.
What's strange is that as soon as I add items to the queue, the queue length becomes defined, 1, 2, 3, ...
and keeps up and syncs the template as I add queue items. So the first $E.get('processingQueue').enqueue('foo')
automagically updates the template to show a queue length of '0', then '1' and so on.
Why is it undefined though before I've enqueued any items? I tried adding gets all over the place according to Unconsumed Computed Properties Do No Trigger Observers but that doesn't seem to help.
Any ideas? It's entirely possible that I misunderstand something about computed properties here, but I don't understand what and why ... I've tried volatile(), [], @each
and all that and I can't get that to make a difference either. Something is not right ...
Any help would be hugely appreciated and I'd be willing to add to the Wiki, write a blog post and maybe release my queue as open source as a thank you. :-)
Thanks! And thanks again for making Ember so awesome!
Aucun commentaire:
Enregistrer un commentaire