Temat: odswiezenie grafiki dopiero po jej pobraniu
Wojciech Mazurek:
zawsze zwraca pusta wartosc ?
Myślę, że żadna z metod nie działa tak jak myślisz :) Generalnie, nie obsługuje się asynchronicznych callbacków, ani tak jak próbowałeś, ani w sposób proponowany przez Andrzeja.
Zacznijmy od tego - jeśli nie czytałeś mojego artykułu o zasięgu i closure w JS, to przeczytaj :P Ten albo inny, jeśli mój jest za słaby :P. Wtedy będziesz wiedział, że kiedy definiujesz funkcję, która jest callbackiem dla "$.get" wewnątrz funkcji "Zapytaj", to ten callback zapamiętuje miejsce swojej definicji. Co rozumiemy przez "zapamiętuje"? Ma dostęp PRZEZ REFERENCJĘ do wszystkich zmiennych, które były dostępne w funkcji "Zapytaj". To jest właśnie closure (domknięcie - czyli "domykanie zasięgu"). To samo zresztą tyczy się funkcji "Zapytaj" - ona też zapamiętuje swój scope, którym w pierwszym przypadku jest m.in. zmienna "s".
Czyli w przypadku:
1) Zapytaj domyka "s". Callback domyka to co jest w Zapytaj, czyli też "s".
2) Zapytaj nic nie domyka, callback domyka "sx".
Idźmy dalej. Teraz równie ważna sprawa - $.get jest asynchroniczną metodą. Oznacza to, że po jego wykonaniu od raz wykonywany jest następujący kod. W tym wypadku zwracany jest "sx/s". Czyli Twoja funkcja Zapytaj zwraca pusty string.
Następnie, po chwili, pobierane są dane z serwera, wywoływany jest callback i on ustawia zmienną "sx/s". I teraz zależnie od przypadku:
1) jako że zmienna "s" była zadeklarowana w scopie najwyżej, to jest ona dostępna TERAZ w każdym innym miejscu tego scope'a. Dlatego jeśli w tym samym scopie masz zadeklarowaną np. metodę obsluzDane(), to ta metoda, jeśli wykonamy ją PO wykonaniu callbacka będzie miała dostęp do danych z serwera.
2) jako że zmienna "sx" zadeklarowana została wewnątrz scope'a funkcji Zapytaj, to tylko funkcje zadeklarowane wewnątrz tej funkcji mają do niej dostep. Czyli nasza obsluzDane() nie będzie widzieć tej zmiennej.
Jakie są sposoby z radzeniem sobie z asynchronicznymi wywołaniami?
1) w callbacku dla $.get() wykonuj funkcję obsługującą dane, której przekażesz te dane jako argument - sposób najbanalniejszy
2) jak w przypadku 1. - deklarujesz zmienną w takim scopie, by funkcje obsługujące te dane widziały tę zmienną i wykonujesz W CALLBACKU funkcję obsługującą dane (tym razem już bez argumentów
3) wykorzystujesz tzw. promise'y, dostępne w jQuery -
http://api.jquery.com/deferred.promise/ i
http://api.jquery.com/category/deferred-object/ pamiętając że $.get zwraca promise'a.
I kolejny raz autopromocja :P. Prowadziłem ostatnio szkolenie i później jeszcze prezentację na tematy związane z asynchronicznością w JS. Tu są slajdy -
http://code42.pl/2011/10/09/moje-prezentacje-z-devmeet...
BTW. ZAWSZE używamy "var". Nie korzystaj nigdy z globalnych zmiennych w innym celu niż do definicji głównego API Twojej aplikacji (najlepiej jednego obiektu, typu window.app).
Piotr Koszuliński edytował(a) ten post dnia 04.11.11 o godzinie 17:25