Aplikacja JavaScript jest podzielona na warstwę logiki i prezentacji. Funkcja warstwy logiki analizuje instrukcje wczytane z pliku. W pewnym momencie jest przejście do warstwy prezentacji, gdzie trzeba coś wyświetlić na ekranie lub oczekiwać na ruch użytkownika (np. kliknięcie obiektu, naciśnięcie klawisza, wybrać akcję). W przeciwieństwie do aplikacji konsolowych GUI (np. dokument HTML) działa cały czas i nie zatrzymuje programu, oczekując na dane wejściowe. Jak zaprojektować komunikację między tymi 2 warstwami, aby uniknąć błędów i zapewnić najlepszą wydajność? Aplikacja działa tak:
function analizuj_kod()
{
switch(instrukcja)
{
case 'prezentacja': funkcja_prezentacji(akcja); break;
//poza tym dużo innych operacji
}
}
function funkcja_prezentacji(akcja)
{
switch(akcja)
{
case 'pokaz_tekst': wypisz(tekst); opoznienie(500); break;
case 'wybierz_obiekt': /* użytkownik ma coś kliknąć lub nacisnąć klawisz */ break;
case 'pobierz_wybor': analizer.id_obiektu = id_obiektu; break; //przekazujemy ID obiektu do logiki
case 'odwtorz_dzwiek': /* odtwarza dzwiek */ break;
//poza tym dużo innych akcji
//nigdzie nie ma return, zawsze przekazujemy dane do analizatora kodu
//ostatecznie można wprowadzić return
}
}
Mam kilka pomysłów:
A. Wątki - Web Workers:
Działają tylko w nowych wersjach przeglądarek. Przykładowy przepływ:
- Tworzymy wątek, w którym będą analizowane instrukcje
- Warstwa logiki wysyła wiadomość do warstwy prezentacji i czeka na odpowiedź
- Warstwa prezentacji wysyła komunikat do warstwy logiki np. po wyborze obiektu
Wątki w JS prawdopodobnie nie obsługują oczekiwania na odpowiedź (nie ma odpowiednika WaitForSingleObject z WinAPI ani Receive z QNX), więc nie przerwiemy wykonywania kodu w danym miejscu. Trzeba to obejść.
B. Wznawianie wykonywania kodu.
- Po wywołaniu funkcji warstwy prezentacji zatrzymujemy analizę kodu.
- Warstwa prezentacji znów uruchamia interpreter: analizer.start() np. po wyborze obiektu.
- Jeśli wywołamy analizer.start() w nieodpowiednim miejscu i czasie, wszystko się posypie.
- Jeśli gdzieś ma być opóźnienie: zatrzymujemy analizę, setTimeout, wznawiamy analizę.
C. Inne pomysły?
Jakie macie pomysły na poprawny i optymalny przepływ sterowania? Co trzeba wiedzieć:
- Interpreter kodu decyduje o przeniesieniu sterowania do prezentacji.
- On także decyduje, czy coś wyświetlić, czy oczekujemy na wejście...
- W aplikacji konsolowej scanf() zatrzymuje przepływ kodu, a tutaj mamy cały czas GUI
- Potrzebny dostęp do stosu interpretera w warstwie prezentacji.
- Obiekty mogą być cały czas widoczne, ale wybór przesyłamy tylko wtedy, gdy warstwa logiki tego chce.