Skip to content

Instantly share code, notes, and snippets.

@stefanpenner
Last active December 15, 2015 01:19
Show Gist options
  • Save stefanpenner/9ccb0503e451a9792ed0 to your computer and use it in GitHub Desktop.
Save stefanpenner/9ccb0503e451a9792ed0 to your computer and use it in GitHub Desktop.

ember-data + Promises

The Promise usage within ember-data needs some TLC.

I often find myself needing to tediously manage multiple events, just to know when a simple action, such as save, has completed. In addition, some of the async actions that return promises never reject. (find*)

I think we have a good foundation, but with some extra thought and work, we can make some drastic improvements.

the idea:

DS.Model is a promise-entity that resolves when the record is loaded, or brought into existence. (find/create) All future saves/updates/commits function calls will not affect this "base promise-entity". Rather these functions will return new promises, that will resolve or reject the record based on the result of the functions intent.

Similarly, ManyArrays and AdapterPopulatedRecordArrayss are promise-entitys that resolve on load.

Top level api improvements/changes

  • find*: -> promise-entity

  • createRecord: -> promise-entity

  • commit: -> promise

  • save: -> promise

  • reload: -> promise

  • commit: -> promise

  • deleteRecord: -> promise

  • RecorArray -> promise will resolve when all its known children are resolved, adding/removing later will not be reflected. Goal #1 is initial load.

record = store.find(Record, 1)
record.then(recordDidLoad, recordFailedToLoad);

// ...
record.save().then(didSave, failedToSave)
record.update().then(didUpdate, failedToUpdate)
record.deleteRecord().then(didDelete, failedToDelete)

record.then(...) // error if record is deleted

record.get('transaction').commit().then(didCommit, failedToCommit)

Underlying changes:

  • Adapter should return promises from all its asynchronous functions
    • For some revs, existing adapters using the non-promise API should be supported with deprecation warnings.
  • Store's corresponding async calls into adapter, should be done with promises
  • all promises must be a+ compliant (ideally RSVP)
  • $.ajax can be used at the edges, but must be must be wrapped by RSVP.wrap
    • jQuery promises have some inconsistencies, which makes mixing them with a+ promises a bad idea.

A point of concern:

Although promises are powerful, it is easy to accidentally allow them to eat important exceptions. This is bad. We may want some or all of the following:

  1. Ability to add a resolver for unhandled errors to a promise chain (would require changes to rsvp).
  2. A dev flag for noisy promises to log all non-propagated errors (or perhaps all errors).
  3. A hook in Ember.Application or DS.Store, for unhandled errors.

The Plan

  • [done] get RSVP#resolve merged in
  • [in-progress + issues] get promises resolved with themselves
  • [in-progress] get RSVP2 into ember
  • [in-progress] get RSVP2 into ember-data
  • assure existing promises actually reject and resolve when one expects them to. (find/create)
  • async methods (save/reload/commit etc..) should return promises.
  • store and adapters async communication should be done via promises.

Related Work

tildeio/rsvp.js#63 emberjs/data#724 emberjs/data#858


Compiled by:

@hjdivad @stefanpenner

@KirillSuhodolov
Copy link

+1

@caifara
Copy link

caifara commented Apr 23, 2013

+1

@l33z3r
Copy link

l33z3r commented Apr 25, 2013

+1

@Goltergaul
Copy link

+1

@vijayj
Copy link

vijayj commented May 16, 2013

This looks great. Any idea when this will get implemented ?

@TrailHacker
Copy link

+1

@ilovett
Copy link

ilovett commented Aug 15, 2013

PLUS ONE

@rodchito
Copy link

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment