Model.fetch conflict if transitional route is directly called #175

Closed
mchaver opened this Issue Nov 28, 2012 · 2 comments

Projects

None yet

3 participants

mchaver commented Nov 28, 2012

Starting with some example code:

get '/', (page, model) ->
  model.del '_parts'
  partsQuery = model.query('parts').partsByCategory('processor')
  model.fetch partsQuery, (err, parts) ->
    model.set '_parts', parts.get()
    page.render()

get from: '/', to: '/build/:category',
  forward: (model, {category}, next) ->
    partsQuery = model.query('parts').partsByCategory(categories[category])
    model.fetch partsQuery, (err, parts) ->
      model.set '_parts', parts.get()
  back: (model, params, next) ->
    model.del '_parts'

get from: '/build/:category', to: '/build/:category',
  forward: (model, {category}, next) ->
    partsQuery = model.query('parts').partsByCategory(categories[category])
    model.fetch partsQuery, (err, parts) ->
      model.set '_parts', parts.get()
  back: (model, params, next) ->
    model.del '_parts'

All routes work except if you directly load "/build/:category" from an outside webpage. In that case, the order of code is everything in "/" except page.render(), then forward in from: "/" to: "/build/:category", then page.render(). I have experimented with the above code, and only model.fetch in the transitional routes. Derby doesn't seem to like it if you call model.fetch from a transitional route before page.render() is called, if model.fetch is called in a transitional route after page.render() then it works fine.

Here is the error that it returns:

throw new Error('Model mutation performed after bundling for clientId: ' + t
        ^
Error: Model mutation performed after bundling for clientId: 1158deae-b56a-472e-9733-4dc297dda3ba

Here is a related thread with more details in the Google Group for Derby

Ziink commented Nov 28, 2012

The problem is that on the server once render() is called (and finishes), any further change to the model will throw this error. In this case, the async method 'fetch()' returns immediately and render() is called.

I see two approaches that the devs could take to fix this:

  1. Any async method on model (server side) should create a promise object that delays the rendering till the promise is resolved. This would not entail any changes to client code.
  2. Check if a promise object is returned from the transitional route. Render only once this promise is resolved. This would entail changes on client code but has the advantage that this could tackle async code that is not model related.

Actually there's a third approach that becomes apparent.

  1. Implement both of the above.
Contributor
nateps commented Jun 5, 2013

Transitional routes now have an optional fourth argument: (model, params, next, done) ->

If the fourth parameter is defined, the route is treated as async and will wait for the done method to be called

@nateps nateps closed this Jun 5, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment