• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Sposób na uniknięcie freezów strony - asynchronizm 'ciężkich' funkcji

Object Storage Arubacloud
+1 głos
387 wizyt
pytanie zadane 3 września 2021 w JavaScript przez Oskar Szkurłat Bywalec (2,780 p.)

Cześć,
Pracuję na projekcie, który korzysta ze sporych danych, co przekłada się freezowanie strony, przy np. przygotowaniu danych do exportu do pdf/xlsx, czy też zaznaczaniu danych w tabeli, rozwijaniu itp. Używam w projekcie devexpress, ale już mam wrażenie, że ustawiłem wszystko co mogłem do optymalizacji, ale wciąż strona zamiera na czas obliczeń.

Rozwiązaniem mojego problemu byłoby znalezienie sposobu na zapewnienie asynchroniczności do moich funkcji, tzn. chciałbym poinformować przeglądarkę, że ma obliczać funkcję tylko, gdy ma "zapas" czasu, tak aby strona nie freezowała się, a obliczenia się wykonywały w tle (ja sobie zapodam wtedy efekt loadingu na komponent).

Jakie są wasze sposoby na to? W głównej mierze zabójcami mojej strony są forEach i map, myślałem żeby je ustawić, jako asynchroniczne i zmusić do spowolnienia czasowego (np. 1ms na iteracje jako 'timeout'), ale mega nie byłbym zadowolony z takiego rozwiązania. Poza tym w przypadku niektórych funkcji (np. wyciąganie danych z dataGrid devexpress) nie mam żadnego wpływu na iteracje w nich zachodzące, bo to biblioteki.

Próbowałem wrzucić np. funkcję do Promise i wyzwalać go w momencie zakończenia obliczeń, ale bez rezultatów, wywołanie promisa też freezuje stronę. Funkcja jest wywoływana po prostu w przycisku na onClick(). Przykład poniżej:

async function onExportPdf(e) {
      try {
        await new Promise((resolve, reject) => {
          const doc = new jsPDF()
          grid.getDataSource().store().load().done().then((data) => {
            const conditions = grid.getCombinedFilter('returnDataField')
            let outDataSource = new ArrayStore(data)
            outDataSource
              .load({ filter: conditions })
              .done((filteredData => {
                doc.autoTable({
                  body: props.options.worksheetExport.getDetails(filteredData),
                  columns: props.options.worksheetExport.columns,
                })
              }))
            doc.save('myFile.pdf')
            e.cancel = true
            resolve()
          })
        })
      } catch (reject) {
        console.error(reject)
      }
    }

Z góry dzięki :)

1 odpowiedź

+3 głosów
odpowiedź 3 września 2021 przez ScriptyChris Mędrzec (190,190 p.)

Próbowałeś ciężkie obliczenia podzielić na wątki?

komentarz 7 września 2021 przez ScriptyChris Mędrzec (190,190 p.)

Jest jakiś problem z zależnościami w tej bibliotece useWorker.

Dlatego jako workaround, na podstawie Twojego kodu, zaimplementowałem tworzenie workera, który ma swoje zależności i jest prawie osobno bundlowany. Całość działa, tylko że bottleneck-iem jest zapisywanie PDF-a. Problem polega na tym, że metoda jsPDF.save korzysta pod spodem z libki file-saver i ona robi jakąś magię na DOM-ie (coś z Canvas-em) do zapisywania plików. Niestety, worker nie ma dostępu do DOM-u, więc o ile proces tworzenia PDF-a na podstawie dostarczonych danych worker ogarnia po swojej stronie, to już do zapisu trzeba dane przesłać do głównego wątku i tam dopiero zapisać (co chwilę trwa).

Można by spróbować do workera wrzucić libkę JSDOM, która zasymuluje DOM i w ten sposób całość zapisu PDF oddelegować do workera. Nie chciało mi się już w to bawić, ale myślę, że powinieneś sobie dać z tym radę na podstawie istniejącej integracji.

Próbowałem pushować poprawiony kod do Twojego repo, ale nie mam do tego uprawnień. Więc albo możesz mi je na chwilę dać (nick ten sam co tutaj) albo wrzucę na swój GitHub i sobie stamtąd całość pobierzesz.

komentarz 7 września 2021 przez Oskar Szkurłat Bywalec (2,780 p.)
edycja 7 września 2021 przez Oskar Szkurłat
Oznaczyłem Cię na githubie, jako collaborator, to powinieneś móc pushować na moim repozytorium (napisane jest, że oczekuje zaproszenie dla Ciebie).
komentarz 7 września 2021 przez ScriptyChris Mędrzec (190,190 p.)

Ok, kod jest na branchu feature/implement-worker. Bundlowanie workera jest uruchamiane komendą npm run prepare-worker. Zależności dla workera dodajesz w pliku src/worker/deps.js. Jednocześnie te, które mają być dostępne w skrypcie workera musisz dodać do obiektu self.WorkerExport i potem w skrypcie do tego namespace się odnosić.

 
komentarz 9 września 2021 przez ScriptyChris Mędrzec (190,190 p.)

@Oskar Szkurłat, i jak - udało Ci się rozwiązać problem? 

1
komentarz 10 września 2021 przez Oskar Szkurłat Bywalec (2,780 p.)

Wybacz, że teraz nie odpisywałem, po prostu musiałem się zająć innymi tematami ;x. Od następnego tygodnia znowu będę siadał do tego :) ale dziękuję w ogóle ślicznie za dotychczasową pomoc ;) mam nadzieję, że mi się uda bez zadawania już pytań. Jak skończę i będzie działać coś więcej, to podrzucę rozwiązanie tutaj na forum dla potomnych.

Podobne pytania

+1 głos
1 odpowiedź 175 wizyt
+1 głos
0 odpowiedzi 145 wizyt
pytanie zadane 14 maja 2019 w JavaScript przez BT101 Stary wyjadacz (12,540 p.)
+1 głos
2 odpowiedzi 632 wizyt
pytanie zadane 9 lipca 2020 w JavaScript przez Greeenone Pasjonat (16,100 p.)

92,536 zapytań

141,377 odpowiedzi

319,452 komentarzy

61,922 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...