Js - funkcja z settimeout wewnątrz innej funkcji - problem z wywołaniem


(czeper) #1

Cześć,

mam tego typu funkję:

var x=10;
funkcja licznik()
{
    if (x>0)
    {
        x--;
        setTimeout("licznik()", 1000)
    }
}

Jest ona wykorzystywana samodzelnie na kilku stronach. Na innej deklaruję taką funkcję:

var y=10;
funkcja licznik2 ()
{
    while (y>0)
    {
x=10;
        licznik();
        y--;
    }
}

Problem w tym że nim ostatecznie wykona się funkcja licznik(), funkcja licznik2() wykonuje wszystkie iteracje pętli. Docelowo iteracja miała zatrzymać się na funkcji licznik(), wykonać ją (miało to trwać 10 sekund), poczym zmniejszyć y i od nowa. Próbowałem też z setinterval, jak również z zastąpieniem pętli instrukcja if dodwaniem na końcu funkcji licznik() linii 

else licznik2();

Zależy mi na tym żeby funkcja licznik() pozostała samodzielna. Macie jakieś propozycje?


(Fizyda) #2

Nie działa bo JS jest asynchroniczny.

  1. Po co ci funkcja licznik jest potrzebna?

  2. Po co odliczasz 10 razy po 1 sekundzie zamiast od razu ustawić setTimeout na te 10 sekund

  3. Czemu używasz zmiennych globalnych które wykorzystujesz lokalnie w funkcji i jeszcze specjalnie je musisz przez to resetować do wartości domyślnej?

EDIT:

Ogólnie programowanie powstało by ułatwić ludziom życie i zautomatyzować wszystko, zastanawiam się teraz tylko czemu Ty postanowiłeś sobie utrudnić życie właśnie przez programowanie.


(czeper) #3

Ile pytań…

To że js jest asynchroniczny, zauważyłem, właśnie dzięki temu przykładowi.

  1. Funkcja licznik nie jest mi potrzebna, potrzebna jest mi inna, bardziej rozbudowana funkcja, a tu został przedstawiony TYLKO PROBLEM. Nie muszę przecież wklejać setek linii kodu żeby przedstawić ten jeden, stosunkowo prosty problem.

  2. Po co odliczam 10 razy co 1 sekundę? Bo co sekundę chcę zmieniać zawartość elementu na stronie. Wiem jak działa funkcja setTimeout, wiem też jak działa funkcja setInterval, więc nie potrzebuję wykładu na ten temat.

  3. Używam zmiennych globalnych bo mam taką potrzebę. Znam zasięg zmiennych, jak przekazywać i zwracać argumenty, więc na ten temat też nie potrzebuję wykładu. Ogólnie mam pętlę w pętli, a skoro dana w wewnętrznej pętli się zeruje, to zewnętrzna, zależna od węwnętrzej musi zresetować zmienną, od której zależy pętla wewnętrzna.

Co do ostatniego pytania: czy to jest sugestia żeby zaprzestać prób programowania? Wiem że nie jestem zaawansowanym programistą i nie przeceniam swoich zdolności, ale tak jak zwykły inżynier nie zaplanuje i nie zbuduje od razu mostu czy wieżowca, tak samo ja nie napiszę od razu skomplikowanego i maksymalnie zoptymalizowanego kodu.

Może przedstawię problem inaczej. Mam fukcję która działa na kilku stronach i wykonuję się wielokrotnie co sekundę (lub 2 albo 10, zależnie od potrzeb) dzięki setTimeout. Gdy pewna wartość dobije do 0, funkcja przestaje działać. Nie chcę powtarzać fragmentów kodu, dlatego na innej stronie chcę napisać funkcję która wykorzysta pierwszą. Może moim błędem było to że pisałem o tym, bo  js jest asynchroniczny i obie funkcje działanią równocześnie i niezależnie i być może muszę napisac jedną funkcję która to spełnia, ale chciałem zobaczyć co do powiedzenia na ten temat mają doświadczeni programiści.


(Drobok) #4

Możesz użyć np webworkera, ale z tym argumentem “skracania kodu” to nie podejdzie :slight_smile:


(Fizyda) #5

W obecnej formie i po Twoim opisie spodziewaj się błędów w działaniu swoich funkcji, ale nie rozpisuję się o tym bo nie potrzebujesz wykładów.

Rozwiązanie jakie możesz zastosować to dodatkowa trzecia funkcja która będzie sprawowała kontrolę nad pozostałymi i to ona będzie swego rodzaju timerem. O tym również się nie rozpisuję bo nie chcę tutaj prowadzić wykładu.

Moje pytanie miało skłonić Cię do przemyślenia jeszcze raz rozwiązania. Ja nigdzie nie napisałem że Twój kod jest za mało skomplikowany czy niezoptymalizowany lecz zawiera błędy bo używasz zmiennych globalnych (do tego w języku asynchronicznym) które są głównym problemem większości błędów i często są gwoździem do trumny dla projektu czy kodu jeśli chodzi o jego utrzymanie, debugowanie czy rozwijanie (zwłaszcza w przypadku kodu asynchronicznego). Ale co ja tam wiem, przecież Ty chciałeś się dowiedzieć co do powiedziani na ten temat mają doświadczeni programiści.


(Frankfurterium) #6

Aktualnie tak sobie. JavaScript jest językiem synchronicznym. Wszelkie asynchroniczne cuda pochodzą z zewnętrznych API oferowanych przez środowiska uruchomieniowe takie jak przeglądarki internetowe albo popularny ostatnio Node.js. Zmieni się to dopiero po oficjalnym wydaniu wersji 6, gdzie częścią specyfikacji są promisy.


(Pablo_Wawa) #7

Widzę, że Ci co tu napisali, w niczym Ci jednak nie pomogli, a nie o to przecież tu chodzi.


(czeper) #8

Przedstawię problem w innej formie (trochę pozmieniam żeby Fizyda się nie czepiał):

function licznik(x)
{
    while (x>0)
    {
       //jakiś kod
        x--;
      
    }
}

function licznik2 (x, y)
{
    while (y>0)
    {
  //jakiś kod
        licznik(x);
        y--;
    }
}

 

Klasyczna pętla w pętli. Ja jednak chciałem zastąpić pętlę while w funkcji licznik() funkcją setTimeout, która wywoła funkcję licznik() x razy co sekundę. Wiem że dzięki funkcjom setTimeout i setInterval tego nie osiągnę. Wydaje mi się że jednak musiałbym napisać jedną funkcję zamiast dwóch. Ale może jednak jest inny sposób na zatrzymanie funkcji licznik 2() do momentu aż funkcja licznik() wykona się x razy co sekundę?


(Fizyda) #9
function licznik(x)
{
    while (x>0)
    {
       //jakiś kod
        x--;
        setTimeout("licznik()", 1000, x);
    }
}


function licznik2 (x, y)
{
    while (y>0)
    {
        //jakiś kod
        licznik(x);
        y--;
        setTimeout("licznik2()", x * 1000, x, y);
    }
}

 


(czeper) #10

Dzięki, o to mi chodziło. Jednak nie wiem czemu, może przez mój błąd, funkcje nie działają jesli x i y przekazywane są jako parametry funkcji. Jeśli pozostawiam nawiasy puste, a x i y deklaruję jako zmienne globalne, wtedy działa.