chaplinjs/chaplin — pull request #441 by mehcode (2013-02-12 03:26:13+00:00)
Title: Initial implementation of XHR request strategizing.

This closes #63.
This is madness (as heard in 300). This truly is a land of madness. Though the implementation works great. :cake: Oh. And I like cake.

This is mostly what we discussed at the bottom of #63. There are 3 primary strategies: **null**, **stack**, and **abort**. **null** does nothing at all (this can be used to no-op this out of your models and collections if you don't want it). **abort** only allows one request at any given time and will abort the current request if another is made. This strategy also aborts the request on dispose. **stack** will keep track of requests but do nothing about it during the lifetime of a model (allows multiple concurrent requests) and on disposal it still does nothing except for one very important detail... no event handlers are called, the request simply finishes and moves along. These can be mixed a bit (ie. you can stack requests during lifetime but abort all current on dispose or do the reverse as in only allow one request but let it finish without calling event handlers).

Some examples (for the sake of brevity assume we're in the context of a model):

```coffee
# Nothing is done to the requests.
strategy: null # or 'null'

# All requests follow the stack strategy all the way through.
strategy: 'stack'

# All requests abort themselves immediately as described above.
strategy: 'abort'

# Requests will abort each other to only allow one
# during sync operations but on dispose the last made
# request will be allowed to finish
strategy:
sync: 'abort'
dispose: null

# Follow specific strategies based on the sync operation.
strategy:
read: 'abort'
create: 'stack'
update: 'stack'
patch: 'stack'
delete: 'abort'

# The default for both models and collections:
strategy:
sync:
read: 'abort'
create: 'stack'
update: 'stack'
patch: 'stack'
delete: 'abort'

dispose:
read: 'abort'
create: 'null'
update: 'null'
patch: 'null'
delete: 'null'
```

Now for a disclaimer. This works great in everything I've tried *so far*. Something of this scale needs at least a week of people poking it before I'd be comfortable with it in master. There are no unit tests at the moment. I'm working on it. I'm submitting the pull now as I'd like some help designing the unit tests for the asynchronous requests. Do we mock `$.ajax`?

---

Oh ... and this `Strategist` object is dead simple to extend with further strategies (such as a request queue) like follows:

```coffee
class Strategist extends Chaplin.Strategist
handlers:
'sync:before':
'queue': (method, options) ->
# Do things

'sync:after':
'queue': (method, request) ->
# Do more things

'dispose':
'queue': (method) ->
# Get rid of things

class Model extends Chaplin.Model
strategy: 'queue'
initStrategist: ->
@strategist = new Strategist {@strategy}
```