A
A
Anar2018-02-11 18:14:11
JavaScript
Anar, 2018-02-11 18:14:11

Is it possible to recurse in js via setTimeout?

As an addiction, I write a function:

function userFadeout2(el, delay, opacity) {
  delay = typeof delay !== 'undefined' ?  delay : 50;

  if(el.style.opacity == "") {
    el.style.opacity = 1;
    opacity = el.style.opacity;
  }
  else if(typeof opacity !== 'undefined') {
    el.style.opacity = opacity;
  }
  else {
    opacity = el.style.opacity;
  }
  
  if(opacity == 0) {
    el.style.display = 'none';
    console.log('конец');
    return true;
  }
  else {
    setTimeout(function() {
      opacity -= 0.1;
      console.log(opacity);
      return userFadeout2(el,delay,opacity.toFixed(1));
    },delay);
  }
}

First implementation
function userFadeout(el, delay) {
  if(el.style.opacity == "") {
    el.style.opacity = 1;
  }
  if(el.style.opacity == 0) {
    el.style.display = 'none';
    return true;
  }
  else if((el.style.opacity -= 0.1) == 0) {
    el.style.display = 'none';
    console.log('конец');
    return true;
  }
  else {
    if(typeof delay != 'undefined' || delay == '') {
      setTimeout(userFadeout, delay, el, delay);
    }
    else {
      console.log(el.style.opacity);
      setTimeout(userFadeout, 50, el);
    }
  }
}

Кучу промежуточных и производных реализация публиковать пожалуй не буду... Логика, я надеюсь и так понятна.

The problem is that the function returns 'undefined' the first time it is called, after which it doesn't return anything else, although 'end' is written to the console after execution and completion.
The experiment shows that if you remove setTimeout, then the function returns true and ends where it is supposed to (after checking for opacity == 0), in the last iteration.
Googling did not find any solution, it would seem that I understood the essence of the problem, but then I realized that I did not understand anything. It is not entirely clear whether recursion occurs at all (apparently not), or whether the "new" function is simply called, and the "old" function ends. In this case, it is not clear why all other functions do not return anything ...
Who can tell what is the deepest mistake and misunderstanding? Or is recursion not possible at all with setTimeout? And in what direction do you look and what to read?
Function console logs
undefined
0.9
0.8
0.7000000000000001
0.6
0.5
0.4
0.30000000000000004
0.19999999999999998
0.1
0
конец

Answer the question

In order to leave comments, you need to log in

4 answer(s)
S
Sergey delphinpro, 2018-02-11
@delphinpro

Throwing away all the excess

if(opacity == 0) {
    ...
    return true;
} else {
  ...
}

we see that if opacity is not equal to zero, then nothing is returned.
Too lazy to delve into, but, most likely, you did not take into account that this is a return from the anonymous function-parameter setTimeout, and not your recursive function.

E
eRKa, 2018-02-11
@kttotto

Everything is correct, it will return undefined. I think you are misunderstanding the execution of setTimout(). Here in this area

else {
    setTimeout(function() {
      opacity -= 0.1;
      console.log(opacity);
      return userFadeout2(el,delay,opacity.toFixed(1));
    },delay);
  }

there will be no waiting for setTimeout to execute, it will create a delayed execution and return undefined, because nothing else is specified. Then setTimeout will run your userFadeout2 function, but it will also return undefined if opacity is not equal to 0.
Too lazy to check, but it seems setTimeout returns delay and your return userFadeout2 won't work as you want. You need to do something like
else {
  $.when(setTimeout(function() {
      console.log("pause");
    },delay)
  ).then(function(){
    opacity -= 0.1;
    console.log(opacity);
    userFadeout2(el,delay,opacity.toFixed(1));
  });
}

This is without checks on the go, as an example, I think you will catch the idea.

A
Alexander Kositsyn, 2018-02-11
@alex_keysi

The function will only return true. Where are you testing the feature in the devtool? The console displays correctly for you. Your function returns undefined on the first call. This is when you launched the function for the first time in the console.
Then the console displays the console logs for you. On the second and so on iterations, the console will no longer display undefined.
Apparently you are testing it in the developer
console. Therefore, such consoles are logs. Your function doesn't return opacity anywhere.
Did you check what you posted in the console?

C
Coder321, 2018-02-12
@Coder321

More or less like this

function userFadeout2(el, delay, opacity) {
    return new Promise((resolve, reject) => {
        delay = typeof delay !== 'undefined' ? delay : 50;

        if (el.style.opacity == "") {
            el.style.opacity = 1;
            opacity = el.style.opacity;
        }
        else if (typeof opacity !== 'undefined') {
            el.style.opacity = opacity;
        }
        else {
            opacity = el.style.opacity;
        }

        if (opacity == 0) {
            el.style.display = 'none';
            console.log('конец');
            return resolve(true)
        }
        else {
            setTimeout(function () {
                opacity -= 0.1;
                console.log(opacity);
                return resolve(userFadeout2(el, delay, opacity.toFixed(1)));
            }, delay);
        }
    })
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question