Skip to content

Instantly share code, notes, and snippets.

@juandopazo
Last active December 10, 2015 23:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juandopazo/4506753 to your computer and use it in GitHub Desktop.
Save juandopazo/4506753 to your computer and use it in GitHub Desktop.
Issues with the current Y.Promise design when writing complex APIs based on promises
// This doesn't work due to some limitations in indexedDB
// It's just an example
// I'd like to be able to write:
Y.IndexedDB.open('mydb').store('myStore').put({
foo: 'bar'
});
/***************************
Promise-based implementation
***************************/
var indexedDB = Y.config.win.indexedDB;
Y.namespace('IndexedDB').open = function (name, version) {
return new IDBDatabase(function (resolver) {
var request = indexedDB.open(name, version);
request.onsuccess = function (e) {
resolver.fulfill(e.target.result);
};
request.onfailure = function (err) {
resolver.reject(err);
};
});
};
function IDBDatabase() {
IDBDatabase.superclass.constructor.apply(this, arguments);
}
Y.extend(IDBDatabase, Y.Promise, {
store: function (storeName) {
var promise = this;
// Notice how we're creating a promise here and there's two calls to `then` which means
// two more promises
return new IDBStore(function (fulfill, reject) {
promise.then(function (db) {
return db.transaction([storeName], "readwrite").objectStore(storeName);
}).then(fulfill, reject);
});
}
});
function IDBStore() {
IDBStore.superclass.constructor.apply(this, arguments);
}
Y.extend(IDBStore, Y.Promise, {
put: function (data) {
return this.then(function (store) {
return store.put(data);
});
}
});
@lsmith
Copy link

lsmith commented Jan 12, 2013

If db.transaction() and/or transaction.objectStore() return promises, there's no difference between what's there currently and

return transaction.objectStore(storeName).then(storePromise.fulfill, storePromise.reject);

If they don't return promises, but could throw, the second promise can be avoided with a try/catch

this.then(function (db) {
    try {
        storePromise.fulfill(db.transaction([storeName], 'readWrite').objectStore(storeName));
    } catch (e) {
        storePromise.reject(e);
    }
});

That said, you're assuming exposed fulfill and reject methods on the instances of IDBStore promises. Maybe you meant

store: function (storeName) {
    var promise = this;

    return new IDBStore(function (fulfill, reject) {
        promise.then(function (db) {
            return db.transaction([storeName], 'readWrite')
                         .objectStore(storeName)
                         .then(fulfill, reject);
        })
    });
}

@juandopazo
Copy link
Author

You are very much right. That's better looking, but it's still 3 promises instead of 1 or 2. Do you have any ideas to improve that?

@juandopazo
Copy link
Author

I just realized I can ignore returning from that promise and avoid creating a third one:

store: function (storeName) {
    var promise = this;

    return new IDBStore(function (fulfill, reject) {
        promise.then(function (db) {
            fulfill(
              db.transaction([storeName], 'readWrite').objectStore(storeName)
            );
        }, reject);
    });
}

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