Comments (23)
I think what you're doing is a good idea. You should be able to pull this off by setting your collection/model to be local, except when you call syncDirtyAndDestroyed
. With 1.1.0, you should be able to do something like:
SomeCollection = Backbone.Collection.extend({
backgroundSync: function() {
this.isSyncing = true;
this.syncDirtyAndDestroyed();
this.isSyncing = false;
},
local: function() { return !this.isSyncing; }
});
It seems like syncDirtyAndDestroyed
ought to always ignore the local
option when saving, since it's intended to be an online operation. I added a commit just now to master that implements this, so you should be able to do this and call syncDirtyAndDestroyed
on your collection:
SomeCollection = Backbone.Collection.extend({
local: true
});
Could you test it out and make sure it works for you?
Since you brought this up, I also just updated the README to document that you can use a function for the local/remote options. Thanks!
from backbone.dualstorage.
Thanks for your quick response!
I'm now playing with the offline collections, and still learning how it works.
One idea: dualStorage was working for me always online, trying connections all the time, but enquing for later the failed connections. That's a killer approach. What I imagine could even be better (I rephrase to make sure we are on the same page) is that dualStorage continues to think it's always online, but every connection is async. So, if I add an item to a collection, it instantly adds it, updates localStorage, and tries a connection or enqueues.
Fetch the index page? No problem! Grab the collection from localStorage, and check if the API is available to grab fresh data. Much like HTML5 manifest: where it loads everything as if offline, and any change to be seen takes another request.
Is your approach of taking the models offline (local: true
) aligned with these ideas?
Thank you very much for your time.
from backbone.dualstorage.
Yes, exactly. local: true
will make everything happen locally (offline); you just need to call syncDirtyAndDestroyed
to try to sync in the background. There is no callback from syncDirtyAndDestroyed to let you know how it went, but you can monitor the events emitted by the collection and model model from the save
and destroy
calls that syncDirty and syncDestroyed make.
Probably the reason it was implemented this way (default to onlineSync
when online) in the first place was the thought that a delayed success response with an up-to-date response seemed preferable to two success callbacks, one for the local/offline sync and one for the online sync (if successful). @lucian1900, does that sound right, or was it thought out that far?
It may be worth thinking about making this the default behavior in the future for the next major release (2.0). Specifically:
- Sync locally first and give an immediate success callback with a status that allows the callback to differentiate whether this response is up to date or cached
- Attempt to sync with the remote, and on success/error, call the appropriate callback again, this time with the server response
- Have Backbone.dualStorage manage detecting the online/offline state, sync retries, etc. This would resolve #4 and #35, and allow for the deprecation of
syncDirtyAndDestroyed
.
If you're interested in having Backbone.dualStorage manage that, I think that would be great. Feel free to discuss with me how you think it should behave, and maybe you can start a new branch to begin work on it. Let me know what you think.
Also please let me know if my change in master allows syncDirtyAndDestroyed
to work properly for models/collections that use local: true
. Thanks!
from backbone.dualstorage.
In the app this was built for initially, the local source was the authoritative one, so a single callback was preferable. There could be a callback passed to syncDirtyAndDestroyed
or attached somewhere else if it's automatic, to find out whether the sync failed.
from backbone.dualstorage.
@tute I'm sorry, it seems that I remembered wrong about setting local: true
. Apparently in local mode, it will not mark models dirty, so syncDirtyAndDestroyed
will have no effect. See https://github.com/nilbus/Backbone.dualStorage/blob/master/backbone.dualstorage.coffee#L235
I could change that line to allow you to pass the dirty: true
option to all your save and destroy calls.
options.dirty = true if options.remote is false and not local
That's really not ideal, but it would work as a workaround for now.
Alternatively, you could set local dynamically only when fetching, but not when saving/destroying. That would get you instant loads from cache and slow/online write operations. Something like:
SomeCollection = Backbone.Collection.extend({
localFirstFetch: function() {
this.localFetching = true;
this.fetch();
this.localFetching = false;
this.fetch();
},
local: function() { return this.localFetching; }
});
What do you think?
from backbone.dualstorage.
Hi, thank you both for your great feedback. Following two ideas sound so good to me:
- Sync locally first and give an immediate success callback with a status that allows the callback to differentiate whether this response is up to date or cached
- Attempt to sync with the remote, and on success/error, call the appropriate callback again, this time with the server response
I was actually wanting so much to have callbacks for both offline and online updates, right now. Having the feedback (for the developer or end users as well) that something is only on your device until you get a better connection or manually sync seems like very healthy to me, right now writing app code that works around it inspecting localStorage["/api/#{collection}_dirty"]
with a setTimeout
after render (as nasty as it sounds! :)).
That's another topic, regarding the local-first behavior I'm still not testing (have to install some software to throttle my connection, will get back to you on it). The idea for fetch()
seems reasonable, but I'll then have the problem for create/update, so I yet wouldn't do it that wat. The use case: slow 3Gs are worse than offline, and turning your phone into airplane mode and not being able to receive calls: not cool. :)
Till next, thank you again very much!
from backbone.dualstorage.
Here's a different flow for a similar problem (I'm sure you already know it, in my to-do list to test and compare): https://github.com/ggozad/Backbone.cachingSync#behavior
from backbone.dualstorage.
I actually was not aware of Backbone.cachingSync. Thank you for bringing it to my attention. I'll have to take a look and see what they're doing too.
I will definitely consider your desired sync behavior for a future release. You have a very compelling use case. Feel free to start on something before I do, if you decide to stick with dualStorage.
from backbone.dualstorage.
Just a heads up: localFirstFetch
working really well, will continue to play with it.
I just changed local: function() { return !this.localFetching; }
to local: function() { return this.localFetching; }
(no negation).
Keep in touch!
from backbone.dualstorage.
I don't understand why do we need local()
to be the negation of localFetching
. Am I understanding the flag backwards?
from backbone.dualstorage.
Awesome, I'm glad that worked for you.
You didn't misunderstand - I got it backward. Whoops! Edited my original comment. :-)
from backbone.dualstorage.
Cool. And my slow action was fetch, all the others are correctly handled (syncing the views instantly, performing the API call for as long as it takes), so I'm really happy with the solution. For the record, it ended up as:
localFirstFetch: (options = {}) ->
@fetch(options)
setTimeout (=>
@localFetching = true
@fetch(options)
@localFetching = false
), 1
local: ->
@localFetching
As I write this I see that I could just change local
as an attribute?
from backbone.dualstorage.
Yes, that would work too and perhaps be a little simpler.
from backbone.dualstorage.
Indeed this is all, getting elegant! :)
localFirstFetch: (options = {}) ->
@fetch(options)
setTimeout (=>
@local = true
@fetch(options)
@local = false
), 1
Checking it with a connection throttler and looking good. Will now try with no timeout.
from backbone.dualstorage.
So with no timeout somehow it doesn't render, that's the best I could come up with. Should we integrate it into the library?
from backbone.dualstorage.
Are you saying the page doesn't render because of a javascript error?
from backbone.dualstorage.
Oh no, it's like if an event is not fired, or something. There has to be a race condition or something, I could spend more time figuring it out why do we need that delay (kind of like a defer
).
from backbone.dualstorage.
ah, I see. I'll have to look into this more later.
from backbone.dualstorage.
I do have an add
listener on a collection, that renders the views, and they don't fire without that setTimeout
. We can work it out together, meanwhile I don't find it too ugly.
from backbone.dualstorage.
I think I might have this sorted. See pull request #86
from backbone.dualstorage.
@tute Do does this solution work the same as #86? Also, what software did you use to throttle your connection?
from backbone.dualstorage.
I don't know if it works exactly the same, we should compare each other's solution. :)
To throttle the connection in my Mac I use http://slowyapp.com/.
from backbone.dualstorage.
I have slowy app too. Not sure if it throttles local host though...
from backbone.dualstorage.
Related Issues (20)
- Save as dirty when Backbone model validation fails. HOT 2
- syncDirtyAndDestroyed() doesn't remove/clear ###_dirty in localStorage HOT 4
- If a collection has never had a model saved successfully to the server, it won't cache failed saves to localStorage HOT 8
- using .toJSON(options) instead of JSON.stringify in create()/update() store methods HOT 1
- "Uncaught TypeError: Cannot read property 'toString' of undefined" when saving without IDs HOT 1
- xhr 200 result of an error HOT 3
- Feature request: add a remote:"never" option per save HOT 4
- Fire event when syncDirtyAndDestroyed is finished HOT 1
- Offline changes with idAttribute seem to break page after refresh HOT 5
- Model.parse should not be called in dualsync HOT 3
- Parsing the string of ids for a collection each time a model updates blocks the main process HOT 1
- Would be better if syncDirty() returned a promise HOT 1
- model id not being set in Store.prototype.create HOT 5
- Destroyed model not being cleared after online sync HOT 2
- Dirty/Destroyed models not be cleared from localStorage after an online sync. HOT 1
- error function not defined HOT 5
- localForage support HOT 1
- QuotaExceededError HOT 1
- Model creation and modification race condition HOT 1
- Fetching remote changes before resolving dirty state HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from backbone.dualstorage.