На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
  
> setTimeout, setInterval
    Здрасте, немного отойду от предыдущей темы :D
    Вот код:
    ExpandedWrap disabled
      function invoke(fn, start, interval, end) {    
          if (arguments.length <= 2) {
              // однократный вызов fn
              setTimeout(fn, start);
          }
          else {
              // многократный вызов fn
              setTimeout(function () {
                  var h = setInterval(fn, interval);
                  if (end) {
                      setTimeout(function() {
                          clearInterval(h);
                      }, end);
                  }
              }, start);
          }  
      }
       
      function foo(){
          console.log('foo');
      }
       
      invoke(foo, 0, 100, 5000); // выполняется вызов foo в течении 5 секунд

    но как остановить вызовы, если не задан параметр end?
    ExpandedWrap disabled
      invoke(foo, 0, 100); // этот код будет выполнятся бесконечно или пока не перезагрузишь страницу

    пробую получить значение h, чтобы потом иметь возможность вызвать clearInterval(h), но как его получить? :wacko:
      сам порешал :D

      ExpandedWrap disabled
        function invoke(fn, start, interval, end) {
            var ret = { timerId: null }; //<-- заводим объект, в которым возратим наш id таймера
         
            if (arguments.length <= 2) {
                setTimeout(fn, start);
            }
            else {
                setTimeout(function (o) {
                    o.timerId = setInterval(fn, interval); //<-- запоминаем
                    if (end) {
                        setTimeout(function() { clearInterval(o.timerId); }, end);
                    }          
                }, start, ret);    
            }
            return ret; //<-- возвращаем
        }
         
        var o = invoke(foo, 10000, 1000);
         
        clearInterval(o.timerId); //<-- теперь можем остановить


      Гениально да? :D
      Сообщение отредактировано: Cfon -
        продолжаем выпендриваться :crazy:
        ExpandedWrap disabled
          <html>
          <head>
           
          </head>
          <body>
          <button onclick="clearInterval( this.Cfon.timerId );">STOP</button>
          <div id="test">TEST</div>
          <script>
        ExpandedWrap disabled
          function invoke( fn, start, interval, end, ret )
          {
              ret = ret || { timerId: null };
              
              ret.timerId = setTimeout( function( ) { if ( interval ) ret.timerId = setInterval( fn, interval ); fn( ); }, start );
              
              if ( end ) setTimeout( function( ) { clearInterval( ret.timerId ) }, end );
          }
        ExpandedWrap disabled
          invoke( function( ) { document.getElementById( 'test' ).innerHTML += ( ' - ' + Math.random() ); ; }, 5000, 300, 30000, document.getElementsByTagName('button')[ 0 ].Cfon = { timerId: null } );
           
          </script>
           
          </body>
          </html>
        Сообщение отредактировано: K313 -
          Цитата K313 @
          продолжаем выпендриваться

          Фигово ты умеешь это делать, однако: https://jsbin.com/katevefato/3/edit?html,js,output :whistle:

          Добавлено
          По ссылке следующий код, кому влом открывать и смотреть:

          ExpandedWrap disabled
            <!DOCTYPE html>
            <html>
            <head>
              <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
            </head>
            <body>
              <button data-bind="click: toggle">
                Жмакни меня!
                <b data-bind="text: i"></b>
              </button>
            </body>
            </html>


          ExpandedWrap disabled
            class Test
              i: ko.observable 0
             
              start: => @allows = setInterval => @i (do @i) + 1, 100
             
              stop: => clearInterval(@allows) or @allows = null
             
              toggle: => if @allows? then do @stop else do @start
             
            ko.applyBindings new Test, document.body
            Цитата Serafim @
            Фигово ты умеешь это делать, однако:
            :yes: да да, конечно, а сам привязал слона к ножке стула и... :whistle:
            Сообщение отредактировано: K313 -
              Цитата K313 @
              да да, конечно, а сам привязал слона к ножке стула и..

              и сделал всё 6ю строчками :D
                Цитата K313 @
                продолжаем выпендриваться :crazy:

                первое, твой код не работает, если не указать параметр end:
                ExpandedWrap disabled
                  invoke( function( ) {
                      document.getElementById( 'test' ).innerHTML += ( ' - ' + Math.random() ); ;
                  }, 5000, 300/*, 30000, document.getElementsByTagName('button')[ 0 ].Cfon = { timerId: null } */);

                я же вначале писал, если не указывать последний параметр, то как остановить?
                второе, я не приветствую указание кода в обработчиках в виде строки :blush:
                ExpandedWrap disabled
                  <button onclick="clearInterval( this.Cfon.timerId );">STOP</button>


                Добавлено
                Цитата Serafim @
                и сделал всё 6ю строчками :D

                сори даже не проверял, ибо не разбираюсь в этом наборе значков :D
                понимаю что сильно отстал от жизни, но как бэ щас вопрос в другом был :blush:

                Добавлено
                а теперь правильный вариант :wild:
                ExpandedWrap disabled
                  function invoke(fn, start, interval, end) {    
                      var timerId; //<-- простая переменная, убираем объект, не надо больше возвращать ничего
                   
                      if (arguments.length <= 2) {
                          setTimeout(fn, start);
                      }
                      else {
                          setTimeout(function () {
                              timerId = setInterval(fn, interval); //<-- запоминаем id
                   
                              if (end) {
                                  setTimeout(function() { clearInterval(timerId); }, end);
                              }          
                          }, start);
                      }
                    
                      // тут внимание! супер-пупер гениальное рещение! )))
                      // определяем замыкание на timerId
                      invoke.stop = function(){
                          clearInterval(timerId);
                      };
                  }
                   
                  invoke(foo, 5000, 1000);
                  invoke.stop();

                Гениально! :D
                Читайте книжки дети! :lool:
                Сообщение отредактировано: Cfon -
                  Цитата Cfon @
                  первое, твой код не работает, если не указать параметр end:
                  если не указан - значит и останавливать не нужно
                  Цитата Cfon @
                  я же вначале писал, если не указывать последний параметр, то как остановить?
                  ну поменяй параметры местами
                  ExpandedWrap disabled
                    function invoke( fn, start, interval, ret, end )
                  если хочешь сам останавливать - указываешь параметр ret, если не хочешь - задаёшь ему false. Так же и с автоматической остановкой параметром end.
                  Цитата Cfon @
                  второе, я не приветствую указание кода в обработчиках в виде строки
                  это не суть, не хочешь - не указывай. Прикрепи слушатель событий или ещё чё. Хранить объект для останова можно где угодно и как угодно, создал глобальную переменную и управляешь, например
                  ExpandedWrap disabled
                    var stop_1 = { timerId : null };
                     
                    invoke( func, 5000, 300, stop_1 );

                  Цитата Cfon @
                  а теперь правильный вариант
                  ты хоть заметил, что в моём варианте можно не только setInterval остановить, но и само начало его запуска, то есть остановить запуск setTimeout. Кроме того, если у тебя задан interval, то первый запуск функции будет не через start милисекунд, как это происходит если параметр interval не задан, а через start + interval милисекунд (то есть у тебя разное поведение)

                  Короче у меня код и в три строчки, и с правильным запуском, и с правильным управлением. А твой ... :bad:

                  Цитата Cfon @
                  Гениально!

                  ExpandedWrap disabled
                    invoke(foo, 5000, 1000);
                    invoke(foo, 5000, 1000);
                     
                    invoke.stop();
                  Гений, какой имено запуск остановить хочешь? :whistle:
                    Цитата K313 @
                    ну поменяй параметры местами
                    ExpandedWrap disabled
                      function invoke( fn, start, interval, ret, end )
                    если хочешь сам останавливать - указываешь параметр ret, если не хочешь - задаёшь ему false. Так же и с автоматической остановкой параметром end.

                    это что за гавнокод? :D

                    Цитата K313 @
                    Цитата Cfon @
                    второе, я не приветствую указание кода в обработчиках в виде строки
                    это не суть, не хочешь - не указывай. Прикрепи слушатель событий или ещё чё.

                    именно суть, ибо по тому как написан код я делаю вывод смотреть его или нет, например вижу такое г меня сразу :bad:

                    Цитата K313 @
                    Кроме того, если у тебя задан interval, то первый запуск функции будет не через start милисекунд, как это происходит если параметр interval не задан, а через start + interval милисекунд (то есть у тебя разное поведение)

                    есть такое дело, но вопрос изначально был как остановить :)

                    Цитата K313 @
                    Короче у меня код и в три строчки, и с правильным запуском, и с правильным управлением. А твой ... :bad:

                    то что ты записал код в три строки не значит, что твой код в три строчки. вот как записывают я (нормальные программеры :jokingly: ), упс уже не три строчки :D
                    ExpandedWrap disabled
                      function invoke( fn, start, interval, end, ret ){
                          ret = ret || { timerId: null };
                          ret.timerId = setTimeout( function() {
                              if ( interval ) {
                                  ret.timerId = setInterval( fn, interval );
                              }
                              fn();        
                          }, start );
                       
                          if ( end ){
                              setTimeout( function( ) {
                                  clearInterval( ret.timerId )
                              }, end );
                          }
                      }



                    Цитата K313 @
                    ExpandedWrap disabled
                      invoke(foo, 5000, 1000);
                      invoke(foo, 5000, 1000);
                       
                      invoke.stop();
                    Гений, какой имено запуск остановить хочешь? :whistle:

                    другое гениальное решение! :D
                    ExpandedWrap disabled
                      function makeInvoker() {
                          var timerId;
                       
                          function invoke(fn, start, interval, end){
                              if (arguments.length <= 2) {
                                  setTimeout(fn, start);
                              }
                              else {                      
                                  timerId = setTimeout(function tick() {
                                      fn();              
                                      timerId = setTimeout(tick, interval); //<-- рекурсивный вызов
                                  }, start);
                                  
                                  if (end) {
                                      setTimeout(function() { clearInterval(timerId); }, end);
                                  }
                              }
                          }
                       
                          invoke.stop = function(){
                              clearTimeout(timerId);
                          };
                       
                          return invoke;
                      }
                       
                      var invoke1 = makeInvoker(),
                          invoke2 = makeInvoker();
                       
                      invoke1(foo, 1000, 1000);
                      invoke2(foo, 3000, 1000);
                       
                      invoke1.stop();
                      invoker2.stop();

                    пс. пофиксил косяк с вызовом invoke.stop() и предыдущий косяк с setInterval, через рекурсивный setTimeout.
                    Сообщение отредактировано: Cfon -
                      :D ну всё, понеслось... :bad::bad::bad:
                        Может забанить на всякий случай? :scratch:

                        Добавлено
                        Цитата Cfon @
                        сори даже не проверял, ибо не разбираюсь в этом наборе значков
                        понимаю что сильно отстал от жизни, но как бэ щас вопрос в другом был

                        Если бы ты пример посмотрел - увидел бы что всё и стартуется и останавливается идеально :tong:
                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                        0 пользователей:


                        Рейтинг@Mail.ru
                        [ Script execution time: 0,0454 ]   [ 16 queries used ]   [ Generated: 28.03.24, 10:53 GMT ]