Coming from a Java background I am now trying to wrap my mind around the asynchronous nature of Javascript. I use promises in my code to do this and until now everything works like a charm, but now I am having a conceptual question and didn't find a definitive answer even after reading the Promise/A+ spec multiple times.
My requirements are this: I have a method that modifies a shared object, stores the update in a PouchDB and reads it back afterwards in order to get an updated revision id field from the db (optimistic locking). Storing and updating the data in Pouch is asynchronous (I am omitting storing "this" to call the methods from within the promises for brevity):
var _doc = ...;var _pouch = new PouchDB(...);function setValue(key, value) { _doc[key] = value; _pouch.put(_doc) .then(function() { return _pouch.get(_doc._id); }) .then(function(updatedDoc) { _doc = updatedDoc; });}
Now, I want to make sure that no other key is set on _doc while it is being written to the db before it has been read again. Is it (a) even possible that another setValue() call is executing a put() (with an outdated revision id) while the get() call from Pouch has not been executed (given the message-queue-approach that JS is using) and (b) if it is possible, is the following solution fail-safe (it is working in my tests, but since I don't know if my tests are considering all possibilities...; storing "this" is again omitted):
var _doc = ...;var _pouch = new PouchDB(...);var _updatePromise;function setValue(key, value) { if (_updatePromise == null) { setValueInternal(key, value); } else { // make sure the previous setValue() call is executed completely before // starting another one... _updatePromise.then(function() { setValueInternal(key, value); }); }}function setValueInternal(key, value) { _doc[key] = value; _updatePromise = new Promise(function(done, reject) { _pouch.put(_doc) .then(function() { return _pouch.get(_doc._id); }) .then(function(updatedDoc) { _doc = updatedDoc; _updatePromise = null; done(); }) catch(function(error) { _updatePromise = null; reject(error); }); });}
I think it should work correctly if fulfilling a promise (calling done()) will synchronously call the next then() function, but I am unable to find a definitive answer whether this is the case.
Any clarification is greatly appreciated and thanks for your help.