Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: use promise-like techniques with the data store #1362

Open
mauritslamers opened this issue May 1, 2016 · 1 comment
Open

Proposal: use promise-like techniques with the data store #1362

mauritslamers opened this issue May 1, 2016 · 1 comment

Comments

@mauritslamers
Copy link
Member

Currently the code for dealing with the store very often requires installing observers on the status of records in order to track the progress of the request(s).
For calls like commitRecords() it is possible to send along one or more callbacks, but the implementation turns out to be a bit buggy.

This proposal is to use promise-like techniques, where the return value of the store can be used to deal with the result of the action:

myStore.commitRecords(myrecs).forEach(function (storeKey) { })

This will take the function given to forEach and then call this function as soon as the request has returned. Especially in combination with array functions (ES6), this pattern becomes powerful as this doesn't need closing over with arrow functions. The this value of arrow functions is taken from the creation moment, not the execution moment.

Something similar can be useful for SC.Request.
The idea came from http://royvanrijn.com/blog/2016/04/deprecating-optional-get/ where a null-check pattern looks rather like the pattern in almost any SC.Request callback:

if (SC.ok(result)) {}

By using promise-like techniques, this pattern can become more expressive, and can be mostly kept inside the state chart where most of these types of action should be initiated. The data source will need to be adjusted as well to properly deal with this.

@mauritslamers
Copy link
Member Author

mauritslamers commented Jun 17, 2016

The following (untested) code implements a promise like system on SC.Request.

SC.Request.reopen({

  /**
    The following functions allow for a more Promise like use of SC.Request. 
    The functions passed in will be called once for every valid record, but only if the result is valid
    If the result is invalid, catch is called instead.
   */
  _initPromise: function () {
    if (!this._promises) this._promises = {};
    // check whether we are already in
    var l = this.get('listeners');
    if (l && l[0] && l[0].findProperty('action', this._handlePromises)) {
      return; // don't add another notifier, one is enough
    }
    else this.notify(this, this._handlePromises);
  },

  _promises: null,

  // being called by notify
  _handlePromises: function (result) {
    var promises = this._promises;
    if (SC.ok(result)) {
      var body = result.get('body');
      if (promises.forEach && body instanceof Array) {
        body.forEach(promises.forEach);
      }
      else if (promises.then) {
        promises.then(body);
      }
    }
    else {
      if (promises.catch) {
        promises.catch(result);
      }
    }
  },

  forEach: function (fn) {
    this._initPromise();
    this._promises.forEach = fn;
    return this;
  },

  then: function (fn) {
    this._initPromise();
    this._promises.then = fn;
    return this;
  },

  catch: function (fn) {
    this._initPromise();
    this._promises.catch = fn;
    return this;
  }
})

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

No branches or pull requests

1 participant