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

question-closed Niespodziewany undefined

Object Storage Arubacloud
0 głosów
241 wizyt
pytanie zadane 30 listopada 2018 w JavaScript przez Davidelo18 Użytkownik (660 p.)
zamknięte 30 listopada 2018 przez Davidelo18

Cześć,

Jestem w trakcie robienia takiej swojej strony. Od razu zaznaczam, że ona jest jeszcze nie responsywna i jeśli szanujecie swój wzrok to nie wchodźcie jeszcze na nią na telefonie :D Layout po kolei robiłem od góry do dołu i wszystko było ok, aż do czasu gdy zauważyłem, że w pliku typing.js wkradł się błąd.

Ogólnie rzecz biorąc kod z tego pliku odpowiada za tę animacje 'pisania' na głównym banerze. I po napisaniu pokazuje, że wartość txtElement czyli zmiennej przechowującej wszystkie nagłówki, gdzie ma być ten tekst napisany jest undefined.

 

Poniżej daje ten kod, który mnie interesuje, jak ktoś woli to daje też link do pełnej strony: https://davidelo18.github.io/one-page-wbst/

 

Struktura HTML:

<div class="banner">
        <hgroup>
            <h1 class="text-type-first typing"></h1>
            <br>
            <h1 class="text-type-second"></h1>
        </hgroup>
        <div class="go-down-btn">\/</div>
    </div>

 

Skrypt JS:

// functions to do after loading the DOM
document.addEventListener('DOMContentLoaded', function () {
    typeWriter();
});

/* --- DECLARED FUNCTIONS AREA --- */

// typing animation the 'welcome' word
const txtElements = document.querySelectorAll('.banner hgroup h1');
const words = ['Welcome!', 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.'];
let currentPosition = 0;
let myIndex = 0;
const delayTime = [300, 90];

function typeWriter() {
    let visibleWord = words[myIndex].substring(0, currentPosition);
    txtElements[myIndex].textContent = visibleWord;

    if (currentPosition < words[myIndex].length) {
        currentPosition++;
        setTimeout("typeWriter()", delayTime[myIndex]);
    } else {
        txtElements[myIndex].classList.remove('typing');
        if(myIndex < words.length){
            myIndex++;
            txtElements[myIndex].classList.add('typing');
            currentPosition = 0;
            setTimeout("typeWriter()", 400);
        }
    }
}
komentarz zamknięcia: Problem rozwiązany :)
2
komentarz 30 listopada 2018 przez kenjiro244 Dyskutant (8,600 p.)
Ok więc błąd pojawia się dopiero na końcu dodaj sobie console.log w tym miejscu gdzie znajduje się błąd i sprawdź co wyświetli ci się jako txtElements[myIndex] kiedy pojawia się błąd prawdopodobnie przekraczasz ilość elementów.
1
komentarz 30 listopada 2018 przez Kondzio Mądrala (5,230 p.)

@Davidelo18, wydaje mi się, że jest to błąd dotyczący indeksów tablicy oraz jej długości. Posprawdzaj to

komentarz 30 listopada 2018 przez pablop76 VIP (123,180 p.)

@Davidelo18,

addEventListener() jako drugi argument nie przekazuj funkcji anonimowej tylko nazwę funkcji callback bez wywołania.

komentarz 30 listopada 2018 przez Davidelo18 Użytkownik (660 p.)

@kenjiro244,

@Kondzio,

Dzięki Wam :D Faktycznie, głupi błąd. Po prostu na końcu myIndex osiągał 2 a elementów w tablicy jest tylko 2, czyli próbował odczytać trzeci element, a takiego nie ma. Dzięki jeszcze raz :D

1 odpowiedź

+1 głos
odpowiedź 30 listopada 2018 przez adrian17 Ekspert (344,860 p.)
wybrane 30 listopada 2018 przez Davidelo18
 
Najlepsza
        if(myIndex < words.length){
            myIndex++;
            txtElements[myIndex].classList.add('typing');

Czyli tak... txtElements ma dwa elementy. myIndex na początku jest 0.

W pierwszej iteracji zwiększasz myIndex do 1, po czym czytasz txtElements[1].

W drugiej iteracji zwiększasz myIndex do 2, po czym czytasz txtElements[2] - wychodzisz poza tablicę.

Wydaje się, że po prostu masz nie do końca dobrze określony warunek końca.

komentarz 30 listopada 2018 przez Davidelo18 Użytkownik (660 p.)
Tak, masz racje. Właśnie ogarnąłem tyle co. Taki głupi błąd ;) Dzięki :D
2
komentarz 30 listopada 2018 przez adrian17 Ekspert (344,860 p.)

To ja tylko dodam jako "reklama", że z async/await ten kod byłby trochę czytelniejszy - rekursja z setTimeout wymusza pilnowanie większego stanu poza funkcję i więcej testów przy każdym wejściu do funkcji. Z async/await kod piszesz "bezpośrednio" - zwykłe dwie pętle, która dla każdego słowa i litery pokazują je z opóźnieniami. To też oznacza mniej bugów ;)

Przykład przepisania Twojego kodu (choć napisany na sucho):

// boilerplate
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }

const txtElements = document.querySelectorAll('.banner hgroup h1');
const words = ['Welcome!', 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.'];
const delayTime = [300, 90];

async function typeWriter() {
    for (let i = 0; i < words.length; ++i) {
        txtElements[i].classList.add('typing');
        for (let c of words[i]) {
            txtElements[i].textContent += c;
            await sleep(delayTime[i]);
        }
        txtElements[i].classList.remove('typing');

        await sleep(400);
    }
}

 

komentarz 30 listopada 2018 przez Davidelo18 Użytkownik (660 p.)

Dzięki wielkie za radę :D async rozumiem że to coś związane z AJAX, asynchronicznym JS? Jeśli tak to jeszcze do niego nie dotarłem, ale pewnie już niedługo :D

3
komentarz 30 listopada 2018 przez adrian17 Ekspert (344,860 p.)

async rozumiem że to coś związane z AJAX, asynchronicznym JS?

Z asynchronicznością tak, z AJAXem niekoniecznie.

async/await to wynik ewolucji języka w celu lepszej obsługi asynchronicznego kodu. Chodzi o to, że kiedy kod wykonuje się "później" (u Ciebie "później" oznacza setTimeout, u innych po otrzymaniu odpowiedzi AJAXem, u innych co innego), ciężko trzyma się stan aplikacji. Widziałeś to sam w swoim kodzie - musiałeś trzymać zmienne globalne, by funkcja przy kolejnych wywołaniach pamietała, na którym słowie/literze była. Z async/await możesz pisać kod "normalnie", tak, jakby był zwykłą funkcją ze zmiennymi lokalnymi etc.

Podobne pytania

0 głosów
1 odpowiedź 83 wizyt
pytanie zadane 17 lutego w JavaScript przez M4jk3l07 Początkujący (290 p.)
0 głosów
1 odpowiedź 362 wizyt
pytanie zadane 12 października 2021 w JavaScript przez krissto7 Gaduła (3,100 p.)
+1 głos
1 odpowiedź 631 wizyt

92,572 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 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!

...