Techniques for avoiding double inserts from an observable subscription

48 views
Skip to first unread message

Jorge Rimblas

unread,
Aug 2, 2017, 2:48:29 PM8/2/17
to KnockoutJS
Hola! I could use your advice.

I have a grid using input elements using data-bind="textInput" (it's used for timesheet entry, so once cell per day)

I subscribe to value changes:

```
  self.val.subscribe(function(newVal) {
    self.save_value(self, parent);
  }.bind(self));
```

And save_value does an AJAX call. As part of my VM I have a "time_entry_id" value that will contain the unique ID from the DB once the record is inserted.  If I have a time_entry_id value, then the backend code will perform an update. Otherwise, it will insert.

The issue, let's say a user enters "7.5".
Call 1: The "7" is sent over. There's no time_entry_id
Call 2: Then the "7.5" is sent over, before Call 1 returns. There is still no time_entry_id because the first call didn't come back yet.
Call 1: Performs an insert.  The Call 2 ALSO performs an insert and we end up with duplicate rows.

My first attempt was to extended the rateLimit on the observable to 1600, but that seems excesive:
self.val = ko.observable(rawEntry.val).extend({ rateLimit: 1600 });

This approach seems much much better:
self.val = ko.observable(rawEntry.val).extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });


It greatly minimizes the issue because I mostly get a very quick reply from the DB.  

Two questions:
1) How do I go ahead and trigger the waiting observables when for example the focus changes?
2) Should I be implementing a different approach?  I could only think of more convoluted ways of tackling this.

Thank you!
-Jorge

noirabys

unread,
Aug 3, 2017, 1:44:48 AM8/3/17
to KnockoutJS
hi,
disable the input field during processing. best way would be to write a custom binding (cb).
 (cb) can access the textInput binding and make a subscription to changes
 (cb) can disable the field during processing
 (cb) may display an error text
 (cb) may show an ajax loader in the field 
 (cb) may delegate the server call to a communication class 
imho i would not recommend the usage of rateLimit at all in this scenario

best regards,
  noirabys

Jorge Rimblas

unread,
Aug 3, 2017, 9:49:54 AM8/3/17
to KnockoutJS
Thank you for the suggestions.

I'm curious, but disabling the input field during processing would greatly affect usability right?  If the user is entering "7.5".  The events would be:
* 7 -> disable
* .  -> still disabled
* re-enabled after AJAX is done
* 5
Instead of 7.5 we could end with 75  Or some permutation of these.

I do like the idea of the AJAX loader right by the field, today the AJAX loader is global for the whole grid and displayed at the top.  A cb makes perfect sense here.

At this point, I may need to implement a server class to delegate and serialize the calls.

Thanks!
-Jorge
Reply all
Reply to author
Forward
0 new messages