use recursive setTimeout instead of setInterval