diff --git a/src/datastore/async_methods/create.js b/src/datastore/async_methods/create.js index eeec354..e2c1a52 100644 --- a/src/datastore/async_methods/create.js +++ b/src/datastore/async_methods/create.js @@ -2,6 +2,11 @@ function errorPrefix(resourceName) { return 'DS.create(' + resourceName + ', attrs[, options]): '; } +function nextPendingId() { + return "ds-pending-" + (nextPendingId.id++); +} +nextPendingId.id = 0; + /** * @doc method * @id DS.async methods:create @@ -79,6 +84,8 @@ function create(resourceName, attrs, options) { if (options.upsert && attrs[definition.idAttribute]) { return DS.update(resourceName, attrs[definition.idAttribute], attrs, options); } else { + var pendingId = nextPendingId(); + return deferred.promise .then(function (attrs) { var func = options.beforeValidate ? DS.$q.promisify(options.beforeValidate) : definition.beforeValidate; @@ -97,6 +104,9 @@ function create(resourceName, attrs, options) { return func.call(attrs, resourceName, attrs); }) .then(function (attrs) { + attrs[definition.idAttribute] = pendingId; + DS.store[resourceName].pendingItems[pendingId] = attrs; + DS.inject(definition.name, attrs, options); return DS.adapters[options.adapter || definition.defaultAdapter].create(definition, options.serialize ? options.serialize(resourceName, attrs) : definition.serialize(resourceName, attrs), options); }) .then(function (res) { @@ -107,7 +117,10 @@ function create(resourceName, attrs, options) { .then(function (data) { if (options.cacheResponse) { var resource = DS.store[resourceName]; - var created = DS.inject(definition.name, data, options); + var pendingItem = DS.store[resourceName].pendingItems[pendingId]; + delete DS.store[resourceName].pendingItems[pendingId]; + DS.eject(resourceName, pendingId, { notify: false }); + var created = DS.inject(definition.name, data, DS.utils.merge(options, { notify: false })); var id = created[definition.idAttribute]; resource.completedQueries[id] = new Date().getTime(); resource.previousAttributes[id] = DS.utils.deepMixIn({}, created); diff --git a/src/datastore/async_methods/destroy.js b/src/datastore/async_methods/destroy.js index e6a615d..798f439 100644 --- a/src/datastore/async_methods/destroy.js +++ b/src/datastore/async_methods/destroy.js @@ -73,6 +73,7 @@ function destroy(resourceName, id, options) { return func.call(attrs, resourceName, attrs); }) .then(function () { + DS.eject(resourceName, id); return DS.adapters[options.adapter || definition.defaultAdapter].destroy(definition, id, options); }) .then(function () { @@ -80,7 +81,6 @@ function destroy(resourceName, id, options) { return func.call(item, resourceName, item); }) .then(function () { - DS.eject(resourceName, id); return id; }); } catch (err) { diff --git a/src/datastore/sync_methods/defineResource.js b/src/datastore/sync_methods/defineResource.js index 5204f86..50f81f6 100644 --- a/src/datastore/sync_methods/defineResource.js +++ b/src/datastore/sync_methods/defineResource.js @@ -269,6 +269,7 @@ function defineResource(definition) { collection: [], completedQueries: {}, pendingQueries: {}, + pendingItems: {}, index: cache, modified: {}, saved: {}, diff --git a/src/datastore/sync_methods/eject.js b/src/datastore/sync_methods/eject.js index b5de090..2af96dd 100644 --- a/src/datastore/sync_methods/eject.js +++ b/src/datastore/sync_methods/eject.js @@ -2,7 +2,7 @@ function errorPrefix(resourceName, id) { return 'DS.eject(' + resourceName + ', ' + id + '): '; } -function _eject(definition, resource, id) { +function _eject(definition, resource, id, options) { var item; var found = false; for (var i = 0; i < resource.collection.length; i++) { @@ -25,7 +25,9 @@ function _eject(definition, resource, id) { delete resource.saved[id]; resource.collectionModified = this.utils.updateTimestamp(resource.collectionModified); - this.notify(definition, 'eject', item); + if (options.notify) { + this.notify(definition, 'eject', item); + } return item; } @@ -67,9 +69,13 @@ function _eject(definition, resource, id) { * @param {string|number} id The primary key of the item to eject. * @returns {object} A reference to the item that was ejected from the data store. */ -function eject(resourceName, id) { +function eject(resourceName, id, options) { var DS = this; var definition = DS.definitions[resourceName]; + + options = options || {}; + options = DS.utils.deepMixIn({notify: true}, options); + if (!definition) { throw new DS.errors.NER(errorPrefix(resourceName, id) + resourceName); } else if (!DS.utils.isString(id) && !DS.utils.isNumber(id)) { @@ -80,10 +86,10 @@ function eject(resourceName, id) { if (!DS.$rootScope.$$phase) { DS.$rootScope.$apply(function () { - ejected = _eject.call(DS, definition, resource, id); + ejected = _eject.call(DS, definition, resource, id, options); }); } else { - ejected = _eject.call(DS, definition, resource, id); + ejected = _eject.call(DS, definition, resource, id, options); } return ejected; diff --git a/src/datastore/sync_methods/inject.js b/src/datastore/sync_methods/inject.js index 5e147dd..74c268a 100644 --- a/src/datastore/sync_methods/inject.js +++ b/src/datastore/sync_methods/inject.js @@ -85,7 +85,9 @@ function _inject(definition, resource, attrs, options) { throw error; } else { try { - definition.beforeInject(definition.name, attrs); + if (options.notify) { + definition.beforeInject(definition.name, attrs); + } var id = attrs[idA]; var item = DS.get(definition.name, id); @@ -121,7 +123,9 @@ function _inject(definition, resource, attrs, options) { resource.observers[id].deliver(); } resource.saved[id] = DS.utils.updateTimestamp(resource.saved[id]); - definition.afterInject(definition.name, item); + if (options.notify) { + definition.afterInject(definition.name, item); + } injected = item; } catch (err) { $log.error(err); @@ -236,6 +240,7 @@ function inject(resourceName, attrs, options) { var definition = DS.definitions[resourceName]; options = options || {}; + options = DS.utils.deepMixIn({notify: true}, options); if (!definition) { throw new DS.errors.NER(errorPrefix(resourceName) + resourceName); @@ -272,7 +277,9 @@ function inject(resourceName, attrs, options) { } } - DS.notify(definition, 'inject', injected); + if (options.notify) { + DS.notify(definition, 'inject', injected); + } stack--; } catch (err) { diff --git a/src/utils.js b/src/utils.js index 102f1a0..822f556 100644 --- a/src/utils.js +++ b/src/utils.js @@ -12,6 +12,7 @@ module.exports = [function () { upperCase: require('mout/string/upperCase'), pascalCase: require('mout/string/pascalCase'), deepMixIn: require('mout/object/deepMixIn'), + merge: require('mout/object/merge'), forOwn: require('mout/object/forOwn'), forEach: angular.forEach, pick: require('mout/object/pick'),