Best way to save to db without slowing down front end

So I currently have series of toggles that look like this

When the user clicks any one of the circles, the workflow runs a simple action to add that social account to the current user’s social accounts. This “social accounts” field on the user table is just a list of texts. In the above example, the user would have facebook,linkedin,twitter as the valueof their social accounts.

As mentioned, these are toggles so if you click one of them off (e.g. click facebook when it’s already checked), then that text value is removed from the current user’s list of social accounts.

This works fine except for when you try to toggle them on or off too quickly as bubble does not queue the requests, instead they just try to modify the user record all at once which can cause issues. Even if they did queue the requests, there is still a delay compared to handling this completely on the front end (i.e. with a custom state or local storage) which makes for a less than ideal customer experience as toggles states are best stored in the front end.

The reason I can’t just handle this all client side is because I need this value to persist across devices, which clearly has to be handled via the db.

So my question is this:
What is the best way to update the db asynchronously? One option I have come up with is to have the circular toggles directly tied to local storage or a custom state and then any time a user clicks on one of the circles, it runs two actions in the workflow:

  1. Set state (to add or remove the value from the list)
  2. Make an api call to a backend workflow that updates the user record with the checkbox “attempt to make the call from the browser”:

That theoretically solves the server side action delay experienced on the front end but comes with two issues:

  1. I remember reading somewhere that this checkbox only does what it says which is “attempt” to make the call. If it can’t then it will run it server side. Additionally I don’t know what would cause it to fail making the call client side and have to revert to server side (maybe it’s only when a CORS issue arises?).
  2. This still doesn’t queue the requests. If two of these backend wf api calls try to modify the user record in too close proximity to one another then the custom state/local storage on the front end could get out of sync with the back end.

The other option is to run the action to update the user record in some workflow that is associated with the user seeing a loading gif elsewhere in my app (i.e. add it to a workflow that already causes the user to have to wait), but the issue with this is that the user may close out of the app before they get to this loading gif section and then the custom state/local storage is now out of sync with the user record.

So long story short, I know I could build out some sort of queuing system but this seems overly complicated or I could just hope the user doesn’t notice the out of sync issue I described in the second option but that’s not ideal either. Either way, I’m wondering if anyone has any better idea of how to solve this.

I’m really hoping there is a super obvious solution that I’m stupidly overlooking.
Thanks in advance

When user clicks the icon, you are already setting custom state. That is usually instantaneous. You can set the icon to be disabled when that custom state is true? You need to make it visually clear that it is disabled by changing icon or by an animation. So, for example that small place where you have a tick-mark, could be a little rotating icon.

And then you can either set that custom state false when data has been updated, or just set it back after a short delay?

My knowledge is limited, but I don’t think you need to create all this calling your own API via API connector etc. Bubble would probably automatically work like this.

This is an async operation. Just create a state called “loading” and set that to true as soon as the operation begins. When the operation is done, set “loading” to off.

Use a conditional to stop the action from happening until the action is set to “no”.

Here’s my approach to something similar.

  • I store the toggle states in a state list or states.
  • Each time a toggle is pressed it will run a “Schedule custom workflow” action, with a condition that checks a different state which I make “true” if the Custom Workflow has been scheduled. This prevents multiple scheduling of the custom workflow.
  • The Custom Workflow runs the “make changes” action
  • Keep the timing for the scheduling short enough so the DB gets updated properly but long enough that it doesn’t keep updating

This ensures the UX stays snappy while ensuring control of your backend actions.

4 Likes

Hi @mghatiya Thanks for your help here but my use case is that I need the toggle to respond instantly and not have any loading delay. I know what you mean and use this solution all the time but it is not the user experience that I want here. I need the toggle to be able to be clicked as often as the user wants.

Thanks for your help but I need the button to react instantaneously.

This is exactly what I need. Thanks so much!

1 Like

So I implemented what you said but wasn’t quite satisfied with the capability for it to be broken (i.e. what you said of “Keep the timing for the scheduling short enough so the DB gets updated properly but long enough that it doesn’t keep updating”)

I wanted it to be foolproof so I modified your technique and came up with this solution:
In the page header, I set these two variables

On the toggle click, run this code:


Here it is for easy copability:
// Clear any existing timeout
if (timeoutId) {
clearTimeout(timeoutId);
}
// Set new timeout
timeoutId = setTimeout(() => {
bubble_fn_save();
// Clear the timeoutId after it’s been triggered
timeoutId = null;
}, 2000);

// Update the start time
dateStarted = new Date();

Then using the JS to bubble element like this:

When the run javascript action is run, it will delay the event to run within 2000 ms. If the user clicks a toggle within 2000 ms, that timeout will get cancelled and it will be delayed another 2 seconds from the most recent click. This way, there is no way for the user to break it.

When the JS to bubble event is run, this is where I update the current user’s appropriate field (the same as your solution).

Hope this helps anyone else.

1 Like

I thought your problem with this approach (:point_up: )you mentioned was this that you mentioned in first post :point_down:

The issue I mentioned about the user closing out of the app was if I was tying the action to update the user record to a different place in the app. A user could not decide to go there.

But the javascript action is tied directly to the toggles and that code has a 2 second delay on it. The only way this could break is if the user clicks one of the toggles and then exits the app in under 2 seconds. If that ever happens that is such a small number of instances that I’m willing for the user to come back in and have to re-click the toggle. This is different than the problem I said in my original post because in the original case, the user has to do an additional step to make sure everything works. Whereas in the second case, the user does not have to do an additional step

Okay, I somehow thought that this was the scenario you mentioned you wanted to cover as well, in your post.

Oh ok. Understood.

Thanks for your help anyway though. Much appreciated.

Nice. I have something running similar to that but the native way is more comfortable for most Bubblers.

Been wanting to do a plugin to facilitate this too.

1 Like

I have put this code into a plugin. Happy to make it open source and share with you if you want.