chaplinjs / chaplin

HTML5 application architecture using Backbone.js
http://chaplinjs.org
Other
2.85k stars 232 forks source link

Collection.reject clashes with deferred reject #540

Closed andriijas closed 11 years ago

andriijas commented 11 years ago

first issue

If you mixin the deferred into your collection the already there reject (whoever uses that one?) gets overwritten.

second issue collection dispose checks if @reject is a function and executes its if so.

Problem is that _.reject expects a function as argument otherwise you get the following stack trace unless the collection is empty.

Which gives you the following stack trace when you try to dispose collections with items:

(am I the only one who faced this problem?) :S

Uncaught TypeError: Cannot call method 'call' of undefined vendor.js:8955
(anonymous function) vendor.js:8955
_.filter._.select vendor.js:8945
_.reject vendor.js:8954
Collection.(anonymous function) vendor.js:10954
module.exports.Collection.dispose vendor.js:18852
module.exports.Nav.dispose app.js:3792
module.exports.Composition.dispose vendor.js:20518
module.exports.Composer._compose vendor.js:18651
module.exports.Composer.compose vendor.js:18629
triggerEvents vendor.js:10207
...
molily commented 11 years ago

The only thing we can do here is to remove the initDeferred and the reject call. If someone wants to use a Deferred, I would recommend to use this.deferred = $.Deferred() for safety reasons.

molily commented 11 years ago

(am I the only one who faced this problem?) :S

If this problem happens with every collection.dispose(), the Collection tests would not pass, but they do.

Which version of Backbone and Underscore are you using?

It seems to work with Backbone 1.0 and Underscore 1.4.4.:

coll = new Backbone.Collection()
coll.reject() # No exception

Are you using Lodash?

andriijas commented 11 years ago

Nope using 1.0/1.4.4. Managed to reproduce it in a bare brunch-with-chaplinn env.

Anyway removing initdeferred sounds legit - can I ask when and how you typically used initdeferred I real world apps? Just want inspiration.

molily commented 11 years ago

A Deferred is a simple way to track the sync or ready state of a model. Typically a model needs to be fetched, but it can also be prefilled from other sources. Then it makes sense to operate on Promises. A consumer does not need to know if it was the standard Backbone sync that made the model “ready”.

At Moviepilot, some models aggregated data from several sources. For example the user has a main Deferred and sub-Deferreds. We needed to get the user data from our server but also from the Facebook Graph API. When both pieces of data were fetched, the main Deferred were resolved.

Chaplin has the SyncMachine which is more powerful for tracking the sync state. It fits smoothly into our memory-safe event-based architecture. I would recommend the SyncMachine for most cases. Deferreds/Promises are more powerful for flows like in the example above.