@robfallows I tried using:
Promise.await(_promiseWrappedSetTimeout());
instead of
await _promiseWrappedSetTimeout();
but it has the same behavior.
My use-case is actually really simple, I have an ordered list of documents (e.g. Documents 1-10) and the user can view any one of those documents as the current active document (e.g. Document 3). This ordering is powered by a field order
on the document and also a field activeDocument
on a parent collection document that holds the current active document’s order
. My use-case is a user can only insert a new document after the current active document.
So when a user clicks a button to insert a new document, the Meteor Method that gets called queries the current activeDocument
and inserts the new document setting its order
to the number one greater than the activeDocument
and then increments the order
of all the documents after the new document and then lastly increments the activeDocument
to make the newly inserted document the active document - this is the important part.
I need to wait for that last update to activeDocument
before firing my Meteor Method again to insert a new document or else the activeDocument
won’t be updated and multiple newly inserted documents all get the same order
- which causes… problems.
So the code looks like this:
Meteor.methods({
insertNewDocument: function(parentId, doc) {
// Query the parent collection to get the current activeDocument (versus trusting the client)
let parentCollection = SomeParentCollection.findOne({parentId}, {fields: {activeDocument: 1}});
// Set the new documents order from the parentCollection
doc.order = parentCollection.activeDocument + 1;
// Insert the new Document
Documents.insert(doc, function(result, error) {
// Update the other documents after this one
_someServerMethodThatUpdatesOtherDocumentsOrder(parentId, doc.order);
// Update the activeDocument
SomeParentCollection.update({parentId}, {$inc: {activeDocument: 1}}, {...});
});
}
});
So I need to block the next Meteor.call("insertNewDocument", order)
until the first one has completely finished all the asynchronous database updates. The problem in the use-case isn’t that I’m waiting for some return value, it’s that if it calls insertNewDocument
repeatedly before waiting for it to return, it will always get the same parentCollection.activeDocument
which messes things up. And the button, method, and functionality should be able to be called quickly, e.g “click”, “click”, “click” to quickly add three new documents.
For my UI, I am disabling the “Insert New Document” button and all of that - which helps, but I want my code to work so that if on the console someone types in:
Meteor.call("insertNewDocument", id, document1);
Meteor.call("insertNewDocument", id, document2);
Meteor.call("insertNewDocument", id, document3);
it works correctly. Even if no one will ever do this, the code needs to work correctly in case someone does or someone tries to screw with it in the console. Its seems like this should easily be possible with Promises
versus using a worker or jobs-queue for something that will complete in 200ms.
If I make the Meteor Method async
it doesn’t work because of the way I’m calling the above commands in the console. I’m not waiting on a result to pass into the next call, I’m just trying to block rapid-fire calls to the method.