CSS-overgange blokeret af JavaScript


Jeg prøver at oprette en indlæsningsbjælke under en meget intensiv periode med JavaScript, hvor nogle ret tunge 3D-arrays bliver bygget og fyldt. Denne indlæsningsbjælke skal forblive tom, indtil brugeren klikker på en knap.

Frysningen opstår uanset om jeg bruger -webkit-transition (Denne app kan være Chrome-eksklusiv, krydsbrowser er ikke nødvendigt i mit tilfælde).

I min søgen efter enkelthed har jeg bygget min bar sådan her...

<div id="loader">
    <div id="thumb">
    </div>
</div>

... og derefter forsøgte at forøge den bar på forskellige stadier af min hoved for løkke:

for(i = 0; i < 5 ; i++){
    document.getElementById('thumb').style.width = i*25 + '%';
    //More Code
}

Problemet er, at alt fryser, indtil JavaScript er færdig. Jeg fandt et lignende spørgsmål på Stack Overflow, Brug af CSS-animation mens JavaScript beregner, og i kommentarerne fandt og overvejede og/eller prøvede jeg følgende:

  • Webarbejdere

    Tro ikke, det vil fungere, da mit script fylder et array med objekter og konstruktører, der indeholder funktioner, hvilket ifølge denne side ikke vil fungere

  • jQuery

    Ikke en mulighed, jeg kan ikke bruge eksterne biblioteker i min app - i hvert fald virker det som lidt overkill at importere et helt bibliotek bare for en indlæsningslinje...

  • Nøglebilleder

    Dette var lovende, og jeg prøvede det, men til sidst fryser det også, så ingen glæde

  • timeOut()er

    Har tænkt på det, men da pointen med indlæsningsbjælken er at reducere frustration, virker det modstridende at øge ventetiden

Jeg ville være glad for at få enhver stigning af baren på dette stadie, selvom den ikke er jævn! Jeg er ret sikker på, at dette er et problem, der har ramt mere end bare mig - måske har nogen en interessant løsning?

P.S.: Jeg poster dette som et nyt spørgsmål i stedet for at tilføje det til det nævnte spørgsmål, da jeg specifikt søger hjælp med JavaScript (ikke jQuery) og ville foretrække, hvis jeg kunne få det ved at bruge en transition (!=animation) på bredden.

Svar #1

Nogle mennesker nævnte allerede, at du burde bruge timeouts. Det er den passende tilgang, fordi det giver browseren tid til at 'trække vejret' og gengive din fremdriftslinje midt i opgaven.

Du bliver nødt til at opdele din kode for at arbejde asynkront. Sig, at du i øjeblikket har noget som dette:

function doAllTheWork() {
  for(var i = 0; i < reallyBigNumberOfIterations; i++) {
    processorIntensiveTask(i);
  }
}

Så skal du gøre det til noget som dette:

var i = 0;
function doSomeWork() {
  var startTime = Date.now();
  while(i < reallyBigNumberOfIterations && (Date.now() - startTime) < 30) {
    processorIntensiveTask(i);
    i++;
  }

  if(i < reallyBigNumberOfIterations) {
    // Here you update the progress bar
    incrementBar(i / reallyBigNumberOfIterations);

    // Schedule a timeout to continue working on the heavy task
    setTimeout(doSomeWork, 50);
  }
  else {
    taskFinished();
  }
}

function incrementBar(fraction) {
  console.log(Math.round(fraction * 100) + ' percent done');
}

function taskFinished() { console.log('Done!'); }

doSomeWork();

Bemærk udtrykket (Date.now() - startTime) < 30. Det betyder, at løkken vil nå at udføre så meget som muligt inden for 30 millisekunder. Du kan gøre dette tal større, men alt over 100 ms (i det væsentlige 10 billeder per sekund) vil begynde at føles langsomt fra brugerens synspunkt.

Det kan være sandt, at den samlede opgave kommer til at tage en smule længere tid ved at bruge denne tilgang i forhold til den synkrone version. Men fra brugerens oplevelse er det bedre at have en indikation på, at noget sker, end at vente uendeligt, mens intet synes at ske - selvom den sidstnævnte ventetid er kortere.

Svar #2

Har du prøvet at gøre det endnu simplere og lave en funktion, lad os sige:

Pseudonym :

Function increment_bar(amount = 10)
{
 document.getElementById('thumb').style.width = i*amount + '%';
}

Så fra hvor som helst du udfører dit behandlingsarbejde, kan du bare kalde den funktion hvert x. sekund eller når du rammer et bestemt punkt i behandlingen (lad os sige 10-20% færdiggørelse?)

Pseudonym :

{
    Doing_work_here;
    increment_bar(25);
    LOOP
}