Add an order for goods by the amount posted

I use this function to add new elements to the sum order. This function is called every 30-50 ms.

var insertBefore = false; container.find('.roll-user-row[data-user-id="' + user_data.id + '"]').remove(); container.children().each(function () { var betContainer = $(this), itemAmount = $(this).attr('data-amount'), betId = $(this).attr('data-user-id'); if (itemAmount < betData.totalAmount) { insertBefore = betContainer; return false; } }); if (insertBefore) { $(template).insertBefore(container); } else { container.prepend(template); } 

itemAmount = $(this).attr('data-amount') is an integer, betData.totalAmount also a betData.totalAmount . And if the addition is slower than ± 300 ms - everything works well. In the case of a quick add, I get this result:

random order

and it doesn’t even close what I want - it’s random. How to solve this?

+5
source share
2 answers

1. Refactoring

First of all, return inside .each callback does not work. It just interrupts the current iteration, not the whole loop. If you want to break the loop, you should use the simple for-loop and break statement. Then I would recommend calling $() as little as possible, because this one is expensive . Therefore, I would suggest the following refactoring for your function:

 function run() { container.find('.roll-user-row[data-user-id="' + user_data.id + '"]').remove(); var children = container.children(); for (var i = 0; i < children.length; i++) { var betContainer = $(children[i]); // to cache children[i] wrapping var itemAmount = betContainer.attr('data-amount'); var betId = betContainer.attr('data-user-id'); if (itemAmount < betData.totalAmount) { $(template).insertBefore(container); return; // instead of "break", less code for same logic } } container.prepend(template); // would not be executed in case of insertBefore due to "return" } 

2. Throttling

To start the 50ms repetition process, you use something like setInterval(run, 50) . If you need to be sure that run is running and this is a 300 ms delay, you can only use setInterval(run, 300) . But if the process is initialized in such a way that you cannot change, and 50 ms is a fixed interval for this, then you can protect the run lodash throttle call or the jquery throttle plugin :

 var throttledRun = _.throttle(run, 300); // var throttledRun = $.throttle(300, run); setInterval(throttledRun, 50); 

setInterval , for example, you need to replace the original run with the throttle version ( throttledRun ) in the repeater initialization logic. This means that run will not be executed until an interval of 300 m has passed from the previous run .

+4
source

I only post the approach here, if my understanding is correct, then I will post the code. The first thing that seemed to me was the Virtual DOM. Here is what you can do

  • Use high-frequency calls of random functions only to maintain a data structure, such as an object. Do not rely on DOM updates.

  • Then use the much less frequent call to the repeating setInterval function to redraw (or update) your DOM from this data structure.

I'm not sure there is any reason why you cannot take this approach, but it will be the most efficient way to handle DOM in critical temporary use.

+2
source

Source: https://habr.com/ru/post/1273066/


All Articles