Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: synchronizacja
Forum PHP.pl > Forum > Po stronie przeglądarki > JavaScript
Kozo_WSP
Czy w javascript jest jakiś prosty mechanizm synchronizacji, tudzież sposób, żeby uzyskać taki efekt.

Klasyczna sytuacja. Dwie funkcje, obie operują na tych samych zasobach. Jedna jest cykliczna np co 5 s. Trwa około 1s. Druga związana z eventem. Funkcja pierwsza ma w swojej treści czekanie setTimeout. Jeśli kliknę w trakcie czekania niestety nie uzyskam żądanego efektu ponieważ na jednym zasobie pracują dwie funkcje.

Rozwiązaniem byłoby synchronizacja między nimi w ten sposób, że druga funkcja czeka na zakończenie pierwszej i wtedy się wykonuje, natomiast kolejne wywołanie funkcji pierwszej nastąpi dopiero po wykonaniu funkcji drugiej.
Crozin
JS jest w pełni jednowątkowy (pomijając Web workery), stąd brak w tym języku jakichkolwiek mechanizmów synchronizacji. Jednak konieczność zsynchronizowania kilku różnych timeoutów wydaje się dosyć podejrzana - mógłbyś opisać swój problem i napisać dlaczego właśnie tak chcesz go rozwiązać? Wygląda na to, że mamy tutaj do czynienia z problemem XY.

Co do samego tematu - prawdopodobnie najłatwiej byłoby utworzyć jakąś kolejkę, gdzie co 5 sekund dodawałbyś pierwszą funkcję, a przy kliknięciu drugą. Samo wykonywanie funkcji z tej kolejki leżałoby w gestii innego obiektu, który mógłby wstrzymywać jej działanie do czasu zakończenia aktualnie przetwarzanej funkcji (łącznie z timeoutami wygenerowanymi w niej).
Kozo_WSP
No niby jednowątkowy, ale jakoś funkcje nie czekają na siebie aż jedna się skończy i zacznie druga. Np. jak mam animację w jQuery i instrukcję za to odpowiadającą. To następna instrukcja zaczyna się wykonywać zanim skończy się animacja...

edit:

może to problem XY, ale już tak daleko w to zabrnąłem... Nie będę przedstawiał problemu, bo jest rozbudowany, a wiem, jak się czyta cudzy kod.
Crozin
Cytat
może to problem XY, ale już tak daleko w to zabrnąłem... Nie będę przedstawiał problemu, bo jest rozbudowany, a wiem, jak się czyta cudzy kod.
Jak jest chociaż w miarę dobrze napisany to się czyta normalnie.
Jeżeli nam nie podasz żadnych istotnych informacji ciężko nam odpowiedzieć na cokolwiek.
Kozo_WSP
Ok, ostrzegam, że to może być szok, bo to mój pierwszy skrypt w js. Także optymalizacyjnie to może być skandal, ale działa to dopóki nie trzeba zmienić slajdu klikając.

Oto slideshow mojego autorstwa:

  1. var tytul = new Array('Nazwa Artykułu','Nazwa drugiego artykułu','Niebieski','Różowy');
  2.  
  3. var opis = new Array('podpis pod artykułem','podpis pod drugim artykułem','Lubię ten kolor', 'a tego nie');
  4. // Dwie tablice, które będą przechowywały krótkie łańcuchy
  5.  
  6.  
  7.  
  8. function slideSwitchNormal() {
  9. //ta funkcja działa jak złoto
  10.  
  11. var nazwa= $(".aa").attr("src");
  12. // mam dwa obrazki na sobie klasy aa i klasy bb będę zmieniał ich przejrzystość i ich źródło src by uzyskać efekt slideshow
  13.  
  14. var liczba = parseInt(nazwa.charAt(8));
  15. // obrazki w folderze mają nazwy 1.jpg, 2.jpg, 3.jpg aby stronę można było generować dynamicznie
  16.  
  17. if(liczba<4)
  18.  
  19. nazwa = "grafika/" + (++liczba).toString() + ".jpg";
  20. //siedzą w folderze grafika
  21. else {nazwa = "grafika/1.jpg"; liczba= 1;}
  22.  
  23. $(".aa").fadeOut("slow");
  24.  
  25. $("p.tytul2").fadeOut("slow");
  26.  
  27. $("p.podpis2").fadeOut("slow");
  28. // mój slideshow to prostokąt na którym oprócz obrazków zmieniają się podpisy
  29. var a = "#but" + liczba;
  30.  
  31. $(a).attr("class", "butC");
  32.  
  33. if ( liczba == 1)a = "#but" + 4;
  34.  
  35. else a = "#but" + (liczba - 1);
  36. // a to buttony, których podświetlenie zmienia się w zależności od tego który slajd jest wyświetlany
  37. $(a).attr("class", "but");
  38.  
  39. setTimeout(function() {
  40. // opóźnienie z powodu, który wymieniłem w poprzednim poście. Animacje nie zdążają się ukończyć przed wykonywaniem kolejnych instrukcji.
  41. $("p.tytul2").text(tytul[liczba - 1]);
  42.  
  43. $("p.podpis2").text(opis[liczba - 1]);
  44. // zmiana opisów
  45. $("p.tytul2").fadeIn("slow");
  46.  
  47. $("p.podpis2").fadeIn("slow");
  48. // wyświetlenie opisów
  49. setTimeout(function() {
  50. // kolejne opóźnienie z tego samego powodu
  51.  
  52.  
  53. $(".aa").attr("src", nazwa);
  54.  
  55. $(".aa").show();
  56.  
  57. ++liczba;
  58.  
  59. if ( liczba > 4)liczba = 1;
  60.  
  61. nazwa = "grafika/" + liczba.toString() + ".jpg";
  62.  
  63. $(".bb").attr("src", nazwa);},2000);},600);
  64.  
  65. }
  66.  
  67.  
  68.  
  69. function slideSwitchEvent( obj) {
  70. // No niestety ta funkcja wszystko niszczy.
  71.  
  72. var liczba = parseInt(($(".aa").attr("src")).charAt(8));
  73. var liczba2 = parseInt(($(obj).attr("id")).charAt(3));
  74.  
  75. var nazwa = "grafika/" + ($(obj).attr("id")).charAt(3) + ".jpg";
  76.  
  77. $(".bb").attr("src", nazwa);
  78.  
  79. $(".aa").fadeOut("slow");
  80.  
  81. $("p.tytul2").fadeOut("slow");
  82.  
  83. $("p.podpis2").fadeOut("slow");
  84.  
  85. var a = "#but" + liczba2.toString();
  86.  
  87. $(a).attr("class", "butC");
  88.  
  89. a = "#but" + liczba.toString();
  90.  
  91. $(a).attr("class", "but");
  92.  
  93. setTimeout(function() {
  94.  
  95. $("p.tytul2").text(tytul[liczba2]);
  96.  
  97. $("p.podpis2").text(opis[liczba2]);
  98.  
  99. $("p.tytul2").fadeIn("slow");
  100.  
  101. $("p.podpis2").fadeIn("slow");
  102. setTimeout(function() {
  103.  
  104.  
  105.  
  106. $(".aa").attr("src", nazwa);
  107.  
  108. $(".aa").show();
  109.  
  110. ++liczba;
  111.  
  112. if ( liczba > 4)liczba = 1;
  113.  
  114.  
  115. nazwa = "grafika/" + (liczba2 - 1) + ".jpg";
  116.  
  117. $(".bb").attr("src", nazwa); },2000); },600);
  118.  
  119. }
  120.  
  121. $(function() {
  122. // co 5s wywoływana zmiana slajdu
  123. setInterval( "slideSwitchNormal()", 5000 );
  124.  
  125. });
  126.  
  127. $("#but1").click(function () {
  128. slideSwitchEvent("#but1");
  129. });
  130. $("#but2").click(function () {
  131. slideSwitchEvent("#but2");
  132. });
  133. $("#but3").click(function () {
  134. slideSwitchEvent("#but3");
  135. });
  136. $("#but4").click(function () {
  137. slideSwitchEvent("#but4");
  138. });
  139. // Prowizoryczne funkcje do klikania, wiem, że to powinna być jedna, używająca this, ale to tylko taka prowizorka żeby sprawdzić

Crozin
Nie analizowałem kodu jakoś specjalnie, więc popraw mnie jeżeli gdzieś jest błąd.

Posiadasz galerię zdjęć, gdzie co 5 sekund ma pojawić się następne zdjęcie. Istnieje jednak możliwość kliknięcia w jakąś miniaturkę/przycisk "dalej" by ręcznie zmienić zdjęcie. Problem jest w tym, że jeżeli w 4 sekundy po samoczynnym zmienieniu się zdjęcia kliknę na następne, już po sekundzie samoczynnie zmienia się ono na kolejne. - Czy ten opis jest poprawny?

1. Powinieneś utworzyć sobie jedną funkcję, która będzie przyjmować jeden argument, tj. zdjęcie do wyświetlenia. Ta funkcja powinna zostać pośrednio wywołana zarówno przez automat (co 5 sekund) jak i przez użytkownika (przy kliknięciu). Pośrednio, czyli jako callback dla setInterval i $.click(); użyjesz innych funkcji, które będą ją wywoływać.
2. setInterval zwraca uchwyt do interwału. Uchwyt ten powinieneś zapisać w jakiejś zmiennej, która będzie ogólnodostępna. W funkcji wywoływanej przy kliknięciu użytkownika zatrzymasz ten interwał (clearInterval) oraz ustawisz go na nowo (ponownie setInterval). Dzięki temu, po kliknięciu zawsze trzeba będzie odczekać 5 sekund na samoczynną zmianę.

Jeżeli coś jest nie tak, wrzuć kod online (np. na jsfiddle.net).
Kozo_WSP
Dzięki za odpowiedź, była bardzo pomocna. Jednak nawet jeśli zastosuje to dla mojego algorytmu, to niestety mam dalej problemy. Dlatego będę chyba musiał go zmienić. Możesz wyjaśnić jak zmieniać obrazki inaczej niż za pomocą attr("src", nowaWartość) ?
Arcioch
Możesz wczytywać wszystkie obrazki z odpowiednim z-index albo wykorzystać parametr opacity lub oczywiście display: none;. Jest to dużo lepsze niż zamiana atrybutu src wink.gif
Kozo_WSP
Mam nadzieję, że nie sprawie kłopotu, jeśli spytam o jeszcze jedną rzecz. Co zrobić, żeby funkcja wykonała się do końca, nawet jeśli nastąpi zdarzenie click podczas jej wykonywania?

Inaczej: Funkcja dokonuje jakichś zmian po kliknięciu. JEśli kliknę kilka razy szybko, to tamte funkcje nie zdążają się wykonać w całości, są przerywane w połowie wykonania, a tego nie chcę. Chcę, żeby jak kliknę dziesięć razy to żeby funkcje wykonały się dziesięć razy od początku do końca.

Niestety kolejki jquery nie są rozwiązaniem bo działają tylko dla animacji. Mogę wymusić żeby za pomocą funkcji queue( funkcja ) animacje wykonywały się w całości, jednak to już nie działa dla funkcji, które dokonują operacji
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.