Tomáš Nosek
Tomáš Nosek

Reputation: 333

How to optimize a script in terms of performance

I have a function called ajaxCall() which simple does the call on a server and returns a value from a feed.

What I wanted to do is to save the value from feed to firstInterval variable, wait 10 seconds, make the call again and save the value to secondInterval variable. And then animate the increasing of these numbers on the webpage. This is what we have so far:

 setInterval(function(){
   getAmounts() 
}, 11000);

function getAmounts(){
  firstInterval = ajaxCall();
  setTimeout(() => {
    secondInterval = ajaxCall();
    animateValue('#bronze-price p', firstInterval, secondInterval, 10000)
  }, 10000);
};

  function animateValue(id, start, end, duration) {
    start = parseInt(start);
    end = parseInt(end);
    var range = end - start;
    var current = start;
    var increment = end > start? 1 : -1;
    var stepTime = Math.abs(Math.floor(duration / range));
    var obj = document.querySelector(id);
    var timer = setInterval(function() {
        current += increment;
        obj.innerHTML = current;
        if (current == end) {
            clearInterval(timer);
        }
    }, stepTime);
}

So the idea is to have a function which gets first interval, after 10 seconds it grabs the second interval and calls the animation. This all is wrapped into setInterval function so I could change the number smoothly repeatedly.

However I am pretty sure that thats not a very clean solution since its setInterval in setTimeout and this all is wrapped in another setInterval function. I am also getting this kind of warnings in the console with both functions:

[Violation] 'setInterval' handler took ms

What would be the best approach to follow up on this idea but optimize the code?

Upvotes: 1

Views: 78

Answers (1)

Yoshi
Yoshi

Reputation: 54649

I think Promises and requestAnimationFrame makes this a lot easier to handle while also getting rid of setTimeout/setInterval. An example would be:

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#Getting_a_random_integer_between_two_values_inclusive
function getRandomIntInclusive(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);

    return Math.floor(Math.random() * (max - min + 1)) + min;
}

// fake api endpoint
const ajaxCall = () => new Promise(resolve => {
    setTimeout(resolve, 400, 1000 + getRandomIntInclusive(0, 1000));
});

// simple animation helper using requestAnimationFrame
const animate = (from, to, duration, cb) => {
    const start = performance.now();

    return new Promise(resolve => {
        requestAnimationFrame(function loop() {
            const f = (performance.now() - start) / duration;

            cb(from + Math.round(f * (to - from)));

            f < 1.0
                ? requestAnimationFrame(loop)
                : resolve();
        });
    });
};

// main
(async (interval) => {
    // where to output
    const dst = document.querySelector('#out');

    // initial value
    let prev  = 0;

    // wait for next value of ajaxCall
    while (true) {
        const next = await ajaxCall();

        console.log(`animating: ${prev} -> ${next}`);

        // animate from `prev` to `next`
        await animate(prev, next, interval, current => {
            dst.innerHTML = current;
        });

        prev = next;
    }
})(10000);
<div id="out"></div>

Upvotes: 1

Related Questions