Skip to content

Instantly share code, notes, and snippets.

@lsmith
Created April 13, 2012 08:37
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lsmith/2375130 to your computer and use it in GitHub Desktop.
Save lsmith/2375130 to your computer and use it in GitHub Desktop.
Ye Olde brainstorm about IO API

Data normalization API proposal

Data API normalization/centralization in three layers

  1. transport layer

  2. transaction layer

  3. encapsulated configuration layer (aka Resource/DataSource)

  4. Transport layer


Goals: encapsulate one method of pipelining data with as little code and as few requirements as possible.

var nativeObject = Y.io.<transport>(source, callback(err, response) {
    /* 'this' is appropriate object */
});

...optionally support context override as third arg to transport function, and pass appropriate object as third arg to callback

###Examples

var scriptNode = Y.io.script(url, function (err, response) {
    /* 'this' is the <script>? */
});

var xhrObj = Y.io.xhr(url, function (err, response) {
    /* 'this' is the XHR object?
*/ });

var func = Y.io.func(this.someMethod, function (err, resp) {
    /* 'this' is ??? */ },
    this); // override context?

Transports

  • xhr
  • xdr
  • form (iframe?)
  • script
  • link
  • flash?
  • socket
  • function/func
  • array
  • object -- see schema for usefulness
  • more...
  1. Transactions

Goals: create encapsulation of lifecycle wrapping transport, standardize API abstraction over transport layer, add events for consistent transaction lifecycle stages plus any stages that are appropriate per transport, support post-response processing

var transaction = Y.io(source, {
    transport: <transport name>,
    type: <post-processor name>,
    on: {
        // or start, end?
        send: callback(e) { /* 'this' and e.transaction are the transaction */ },
        response: callback(e) { /* same, plus e.response is the transport response */ },
    }
    after?
    context?
    args?
});

Alternate signatures

var transaction = Y.io(source, callback(e) { /* e.response */ } [, context?]);
var transaction = Y.io(source, { config, but without on: {...} }, callback(e) { /* e.response */ } [, context?]);
var transaction = Y.io(source, <type>, callback(e) { /* e.response */ });

Transport-specific configuration

Other configuration attributes/properties interpreted by the transport/type modules or generic feature modules/plugins, such as:

  • method: ('get', 'post', 'put', 'delete', 'head')
  • multipart: true || separatorString?
  • sync: false
  • headers: { 'content-type': 'application/json' }
  • queuing: true
  • polling: true || msInterval || { more config? }
  • disabledFields: false
  • native: true - for xdr transport
  • data: ... - form data or maybe form Node or id
  • timeout: ms
  • schema - e.g.
schema: {
    resultListLocator: 'records.here',
    resultFields: [ ... ]
    output: ('array', 'arraylist', ModelList, MyArrayListSubclass, more?)
}

Other events interpreted by the transport

on: {
    success: callback(e) { ... },
    failure: callback(e) { ... }
}

Default transport

Y.io will default transport based on a test function on each transport, and/or set by the 'type' configuration.

CAVEAT: transport test-based defaulting could create confusion for JSONP vs XHR

var useAsDefault = Y.io.script.test(source, config); // => true/false/likelihood rating

var transaction Y.io('/service', function (e) {
    /* xhr transport passes test, is used */
});

// types can default transport
var transaction = Y.io('http://servi.ce/foo', { type: 'jsonp' }, function (e) {
    /* 'script' transport defaulted */
});

// types and transports can be incompatible
var boom = Y.io(source, { transport: 'link', type: 'jsonp' }, ...); // boom === null
  1. Encapsulated configuration

Goals: Create transaction factories with configured defaults.

Use same/similar API signature to Y.io().

NAMING DISCUSSION: Y.DataSource, Y.Resource, Y.io.Resource, other?

var resourceA = new Y.DataSource(url/data, { ... });

var transaction = resourceA.send(extra/data, {
    /* config overrides, plus transaction level... */
    on: { ... }
}, contextOverride?);

// Transaction object points back to originating resource
transaction.resource; // => resourceA

// Post-creation subscription possible
transaction.on('success', fn);
transaction.after('end', fn);

// Transport-specific API decoration?
transaction.abort();
  1. (bonus!) Widget extension API

Goals: normalize API for data layer configuration of Widgets (and others?)

Mirror the DataSource/IO API, but with 'source' property in configuration object taking the place of the leading url/source argument. Widget attribute should be 'data' (debatable).

var table = new Y.DataTable({
    data: {
        source: url,
        type: 'jsonp',
        schema: {
            resultListLocator: 'records',
            ...
        }
    },
    columns: [ ... ]
});

table.load( <sig args for dataSourceInstance.send( ... )> );

var chart = new Y.Chart({
    data: {
        source: url,
        type: 'jsonp',
        schema: {
            resultListLocator: 'records',
            ...
        }
    },
    type: 'pie'
});

chart.load( <sig args for dataSourceInstance.send( ... )> );
@lsmith
Copy link
Author

lsmith commented Sep 4, 2012

Deferred/promises proposal at lsmith/yui3#36

Feedback here pertaining to how it would fit the transaction layer, structural/code feedback on the pull request, please :)

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