Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Overview of Orbit.js

Overview of Orbit.js

Overview of Orbit.js and how it can be used with Ember.js. Presented at the Boston Ember meetup February 21, 2018.

Dan Gebhardt

February 21, 2018
Tweet

More Decks by Dan Gebhardt

Other Decks in Programming

Transcript

  1. @ d g e b B o s t o

    n E m b e r M e e t u p F e b r u a r y 2 0 1 8
  2. TRANSFORMS Transforms consist of an array of operations: [{"op": "addRecord",

    "record": { type: 'planet', id: 'p1', attributes: { name: 'Jupiter' }}} {"op": "addRecord", "record": { type: 'moon', id: 'm1', attributes: { name: 'Io' }}}, {"op": "addToRelatedRecords", "record": { type: 'planet', id: 'p1' }, "relationship": "moons", "record": { type: 'moon', id: 'm1' }}]
  3. BUILDING TRANSFORMS Transform builders improve ergonomics: store.update(t => [ t.addRecord(jupiter),

    t.addRecord(io), t.addToRelatedRecords(jupiter, 'moons', io) ]);
  4. QUERY EXPRESSIONS An example query expression for finding a sorted

    collection: { op: 'findRecords', type: 'planet', sort: [{ kind: 'attribute', attribute: 'name', order: 'ascending' }] }
  5. @ o r b i t / c o o

    rd i n a t o r
  6. SYNC'ING CHANGES // Sync all changes to the store with

    backup coordinator.addStrategy(new SyncStrategy({ source: 'store', target: 'backup', blocking: true }));
  7. OPTIMISTIC UPDATES // Push update requests to the server. coordinator.addStrategy(new

    RequestStrategy({ source: 'store', on: 'beforeUpdate', target: 'remote', action: 'push' }));
  8. PESSIMISTIC UPDATES // Push update requests to the server. coordinator.addStrategy(new

    RequestStrategy({ source: 'store', on: 'beforeUpdate', target: 'remote', action: 'push', blocking: true }));
  9. HANDLING FAILURES (1/2) coordinator.addStrategy(new RequestStrategy({ source: 'remote', on: 'pushFail', action(transform,

    e) { if (e instanceof NetworkError) { // When network errors are encountered, try again in 5s console.log('NetworkError - will try again soon'); setTimeout(() => { remote.requestQueue.retry(); }, 5000); } // Else see Part 2 }, blocking: true }));
  10. HANDLING FAILURES (2/2) // When non-network errors occur, notify the

    user and // reset state. let label = transform.options && transform.options.label; if (label) { alert(`Unable to complete "${label}"`); } else { alert(`Unable to complete operation`); } // Roll back store to position before transform if (store.transformLog.contains(transform.id)) { console.log('Rolling back - transform:', transform.id); store.rollback(transform.id, -1); } return remote.requestQueue.skip();
  11. BROWSER STORAGE // Warm the store's cache from backup BEFORE

    activating // the coordinator backup.pull(qb.records()) .then(transforms => store.sync(transforms)) .then(() => coordinator.activate());
  12. import { Model, attr, hasMany } from 'ember-orbit'; Star =

    Model.extend({ name: attr('string'), planets: hasMany('planet', {inverse: 'sun'}) }); Planet = Model.extend({ name: attr('string'), classification: attr('string'), sun: hasOne('star', {inverse: 'planets'}) }); Model ember-orbit
  13. // Given a `model` from a `store` let fork =

    store.fork(); let forkModel = this.fork.cache.find(model.type, model.id); fork .addRecord({ type: 'phoneNumber' }) .then(phoneNumber => { forkModel.get('phoneNumbers').pushObject(phoneNumber); }); // `merge` coalesces operations to a minimal set before // applying the update store.merge(fork); Store Forking ember-orbit