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

question-closed Ajax JS PHP problem z wynikiem

0 głosów
412 wizyt
pytanie zadane 13 listopada 2019 w JavaScript przez karoloo Użytkownik (530 p.)
zamknięte 13 listopada 2019 przez karoloo

Witam. Mam pewien problem z JavaScriptem. Wysyłam zapytanie do PHP 

                    var xmlhttp = new XMLHttpRequest();
                    xmlhttp.open("GET", "spinuj.php?q=" + str, true);
                    xmlhttp.send();

Następnie odbieram wynik

xmlhttp.onreadystatechange = function() {
                if (this.readyState == 4 && this.status == 200) {
                    firstspin = this.responseText;
                    console.log(firstspin)
                }

Całość znajduje się w funkcji o następującej postaci 

function showHint() {
            var str="d";
            var firstspin;
            if (str.length == 0) {
                document.getElementById("txtHint").innerHTML = "";
                return;
            } else {
                    var xmlhttp = new XMLHttpRequest();
                    xmlhttp.open("GET", "spinuj.php?q=" + str, true);
                    xmlhttp.send();
            }
            xmlhttp.onreadystatechange = function() {
                if (this.readyState == 4 && this.status == 200) {
                    firstspin = this.responseText;
                    console.log(firstspin) // poprawna wartość 
                }
            };
console.log(firstspin) // wartość undefined
// poza funkcją firstspin przyjmuje wartość undefined
        }

Problem oznaczyłem komentarzami w kodzie wyżej. Zmienna firstspin ma poprawną wartość jedynie wewnątrz funkcji " xmlhttp.onreadystatechange = function() {", a poza nią przyjmuje wartość undefined. Od kilku dni nie potrafię odnaleźć rozwiązania tego problemu. Próbowałem już taktyki typu przypisania wartości tej funkcji np w value ukrytego inputa i odczytaniu value poza funkcją. Bardzo proszę o pomoc.

komentarz zamknięcia: Problem rozwiązany

2 odpowiedzi

+1 głos
odpowiedź 13 listopada 2019 przez ScriptyChris Mędrzec (190,170 p.)
wybrane 13 listopada 2019 przez karoloo
 
Najlepsza

Zapoznaj się z zagadnieniem asynchroniczności w JavaScript.

Wysyłasz żądanie XHR, które jest asynchroniczne. Oznacza to, że odpowiedź na to zapytanie wróci "kiedyś" lub "nigdy", ale nie "od razu". Funkcja podpięta do xmlhttml.onreadystatechange wywoła się po console.log(firstspin), stąd w miejscu logowania do konsoli nie masz jeszcze wartości w zmiennej firstspin - poczytaj o run-to-completion.

Możesz wymusić synchroniczną obsługę XHR, poprzez ustawienie parametru async na false w momencie wywołania metody xmlhttp.open. Jednak nie jest to zalecane, ponieważ wtedy zablokujesz wątek do czasu otrzymania odpowiedzi.

Co chcesz dalej zrobić ze zmienną firstspin?

komentarz 13 listopada 2019 przez karoloo Użytkownik (530 p.)
edycja 13 listopada 2019 przez karoloo
Po ustawieniu na false otrzymuje błąd w konsoli

[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

Wynik przyjmuje wartość undefinned.
1
komentarz 13 listopada 2019 przez ScriptyChris Mędrzec (190,170 p.)

Synchroniczność jest uruchomiona

Nie. Parametr z wartością true ustawia asynchroniczność. Żeby zapytanie było synchroniczne, musisz podać tam false.

Wynika z tego że najpierw wykonuje się dalsza cześć kodu, więc jak zablokować wywoływanie kodu dopóki firstspin nie zdobędzie wyniku?

O tym właśnie pisałem w odpowiedzi. Podlinkowałem też pomocne materiały.

Docelowo do php wysłanych będzie kilka wartości i oczekiwanych będzie kilka odpowiedzi które będą zależeć od dalszego wykonania strony tzn zwrócą informacje co ma pojawić się na stronie.

Jeśli planujesz wykonać kilka zapytań pod rząd i każde kolejne ma zależeć od odpowiedzi z poprzedniego, to tutaj dobrze sprawdzi się użycie konstrukcji async / await, dzięki której pisany kod będzie wyglądał na synchroniczny, mimo że pod spodem będzie asynchroniczny.

komentarz 13 listopada 2019 przez karoloo Użytkownik (530 p.)
Przepraszam, ale źle przeczytałem wiadomość i myślałem że chodziło o wartość true, aby wiadomość była synchroniczna. Zaktualizowałem odpowiedź z 4 minuty temu
komentarz 13 listopada 2019 przez karoloo Użytkownik (530 p.)

Po ustawieniu na false otrzymuje błąd w konsoli

[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

Wynik przyjmuje wartość undefinned.

1
komentarz 13 listopada 2019 przez ScriptyChris Mędrzec (190,170 p.)

Skorzystaj z async / await. Jeśli jednak wolisz pozostać przy callbackach (bo nie znasz "nowszej" składni JavaScript), to w funkcji podpiętej do xmlhttp.onreadystatechange utwórz nowy obiekt XHR i wyślij go przekazując dane z pierwszego... i tak z każdym kolejnym - tym sposobem utworzą Ci się zagnieżdżone callbacki i poznasz czym jest Callback Hell. :)

komentarz 13 listopada 2019 przez karoloo Użytkownik (530 p.)
Dzięki za pomoc i poświęcony czas :D
0 głosów
odpowiedź 13 listopada 2019 przez pseudoExpert Obywatel (1,300 p.)
Tak na wyczucie i bez testowania.

Spróbuj przenieść instrukcję " var firstspin; " poza funkcję " showHint() ".

Czyli usuwasz ją z ciała funkcji i umieszczasz w kodzie jako zmienną globalną.

Ważne aby zmienna była zadeklarowana zanim zostanie wywołana funkcja.

Jeśli to pomogło to super jeśli nie ... nie pomogę.

Podobne pytania

0 głosów
1 odpowiedź 356 wizyt
pytanie zadane 13 stycznia 2017 w PHP przez KONDZIU Użytkownik (550 p.)
0 głosów
1 odpowiedź 779 wizyt
0 głosów
1 odpowiedź 304 wizyt

93,772 zapytań

142,730 odpowiedzi

323,382 komentarzy

63,369 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

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...