Непрерывное функционирование функции при изменении размера страницы [дубликат]

В то время как обещания и обратные вызовы хорошо работают во многих ситуациях, боль в задней части выражает нечто вроде:

if (!name) {
  name = async1();
}
async2(name);

. В итоге вы пройдете через async1; проверьте, не определено ли name или нет, и соответственно вызовите обратный вызов.

async1(name, callback) {
  if (name)
    callback(name)
  else {
    doSomething(callback)
  }
}

async1(name, async2)

Хотя в в порядке хорошо , это раздражает, когда у вас много подобных случаев и обработка ошибок.

Fibers помогает в решении проблемы.

var Fiber = require('fibers')

function async1(container) {
  var current = Fiber.current
  var result
  doSomething(function(name) {
    result = name
    fiber.run()
  })
  Fiber.yield()
  return result
}

Fiber(function() {
  var name
  if (!name) {
    name = async1()
  }
  async2(name)
  // Make any number of async calls from here
}

Вы можете проверить проект здесь .

205
задан katalin_2003 20 July 2014 в 02:34
поделиться

20 ответов

Мне повезло со следующей рекомендацией: http://forum.jquery.com/topic/the-resizeend-event

Вот код, чтобы вы не придется прорыть ссылку на его сообщение & amp; источник:

var rtime;
var timeout = false;
var delta = 200;
$(window).resize(function() {
    rtime = new Date();
    if (timeout === false) {
        timeout = true;
        setTimeout(resizeend, delta);
    }
});

function resizeend() {
    if (new Date() - rtime < delta) {
        setTimeout(resizeend, delta);
    } else {
        timeout = false;
        alert('Done resizing');
    }               
}

Спасибо sime.vidas за код!

154
ответ дан Timothy Gonzalez 28 August 2018 в 21:16
поделиться
var flag=true;
var timeloop;

$(window).resize(function(){
    rtime=new Date();
    if(flag){
        flag=false;
        timeloop=setInterval(function(){
            if(new Date()-rtime>100)
                myAction();
        },100);
    }
})
function myAction(){
    clearInterval(timeloop);
    flag=true;
    //any other code...
}
0
ответ дан babak iran 28 August 2018 в 21:16
поделиться

Хорошо, что касается диспетчера окон, каждое событие изменения размера является его собственным сообщением с четким началом и концом так технически, каждый раз, когда размер окна изменяется, это конец.

Сказав это, возможно, вы хотите установить задержку для продолжения? Вот пример.

var t = -1;
function doResize()
{
    document.write('resize');
}
$(document).ready(function(){
    $(window).resize(function(){
        clearTimeout(t);
        t = setTimeout(doResize, 1000);
    });
});
465
ответ дан Blazemonger 28 August 2018 в 21:16
поделиться

это работало для меня, поскольку я не хотел использовать какие-либо плагины.

$(window).resize(function() {
    var originalWindowSize = 0;
    var currentWidth = 0;

    var setFn = function () {
        originalWindowSize = $(window).width();
    };

    var checkFn = function () {
        setTimeout(function () {
            currentWidth = $(window).width();
            if (currentWidth === originalWindowSize) {
                console.info("same? = yes") 
                // execute code 
            } else {
                console.info("same? = no"); 
                // do nothing 
            }
        }, 500)
    };
    setFn();
    checkFn();
});

В окне re-size вызывается «setFn», который получает ширину окна и сохраняет как «originalWindowSize». Затем вызывается «checkFn», который после 500 мс (или ваших предпочтений) получает текущий размер окна и сравнивает оригинал с текущим, если они не совпадают, тогда окно все еще изменяется. Не забудьте удалить консольные сообщения в процессе производства, и (необязательно) может выполнить «setFn» самостоятельно.

0
ответ дан Byron Wong 28 August 2018 в 21:16
поделиться

, так как выбранный ответ на самом деле не работает .. и если вы не используете jquery здесь, это простая функция дроссельной заслонки с примером того, как ее использовать при изменении размера окна

    function throttle(end,delta) {

    var base = this;

    base.wait = false;
    base.delta = 200;
    base.end = end;

    base.trigger = function(context) {

        //only allow if we aren't waiting for another event
        if ( !base.wait ) {

            //signal we already have a resize event
            base.wait = true;

            //if we are trying to resize and we 
            setTimeout(function() {

                //call the end function
                if(base.end) base.end.call(context);

                //reset the resize trigger
                base.wait = false;
            }, base.delta);
        }
    }
};

var windowResize = new throttle(function() {console.log('throttle resize');},200);

window.onresize = function(event) {
    windowResize.trigger();
}
0
ответ дан Chad Brown 28 August 2018 в 21:16
поделиться

UPDATE!

Лучшая альтернатива, также созданная мной, находится здесь: https://stackoverflow.com/a/23692008/2829600 (поддерживает «функции удаления»)

ORIGINAL POST:

Я написал эту простую функцию для обработки задержки выполнения, полезной внутри jQuery .scroll () и .resize () Таким образом, callback_f будет запускаться только один раз для определенной строки идентификатора.

function delay_exec( id, wait_time, callback_f ){

    // IF WAIT TIME IS NOT ENTERED IN FUNCTION CALL,
    // SET IT TO DEFAULT VALUE: 0.5 SECOND
    if( typeof wait_time === "undefined" )
        wait_time = 500;

    // CREATE GLOBAL ARRAY(IF ITS NOT ALREADY CREATED)
    // WHERE WE STORE CURRENTLY RUNNING setTimeout() FUNCTION FOR THIS ID
    if( typeof window['delay_exec'] === "undefined" )
        window['delay_exec'] = [];

    // RESET CURRENTLY RUNNING setTimeout() FUNCTION FOR THIS ID,
    // SO IN THAT WAY WE ARE SURE THAT callback_f WILL RUN ONLY ONE TIME
    // ( ON LATEST CALL ON delay_exec FUNCTION WITH SAME ID  )
    if( typeof window['delay_exec'][id] !== "undefined" )
        clearTimeout( window['delay_exec'][id] );

    // SET NEW TIMEOUT AND EXECUTE callback_f WHEN wait_time EXPIRES,
    // BUT ONLY IF THERE ISNT ANY MORE FUTURE CALLS ( IN wait_time PERIOD )
    // TO delay_exec FUNCTION WITH SAME ID AS CURRENT ONE
    window['delay_exec'][id] = setTimeout( callback_f , wait_time );
}


// USAGE

jQuery(window).resize(function() {

    delay_exec('test1', 1000, function(){
        console.log('1st call to delay "test1" successfully executed!');
    });

    delay_exec('test1', 1000, function(){
        console.log('2nd call to delay "test1" successfully executed!');
    });

    delay_exec('test1', 1000, function(){
        console.log('3rd call to delay "test1" successfully executed!');
    });

    delay_exec('test2', 1000, function(){
        console.log('1st call to delay "test2" successfully executed!');
    });

    delay_exec('test3', 1000, function(){
        console.log('1st call to delay "test3" successfully executed!');
    });

});

/* RESULT
3rd call to delay "test1" successfully executed!
1st call to delay "test2" successfully executed!
1st call to delay "test3" successfully executed!
*/
0
ответ дан Community 28 August 2018 в 21:16
поделиться

Я написал функцию, которая передает функцию при завершении любого события изменения размера. Он использует интервал, так что изменение размера даже не постоянно создает события таймаута. Это позволяет выполнять независимо от события изменения размера, отличного от записи в журнале, которое должно быть удалено в процессе производства.

https://github.com/UniWrighte/resizeOnEnd/blob/master/resizeOnEnd.js

        $(window).resize(function(){
            //call to resizeEnd function to execute function on resize end.
    //can be passed as function name or anonymous function
            resizeEnd(function(){



    });

        });

        //global variables for reference outside of interval
        var interval = null;
        var width = $(window).width();
    var numi = 0; //can be removed in production
        function resizeEnd(functionCall){
            //check for null interval
            if(!interval){
                //set to new interval
                interval = setInterval(function(){
        //get width to compare
                    width2 = $(window).width();
        //if stored width equals new width
                    if(width === width2){
                        //clear interval, set to null, and call passed function
                        clearInterval(interval);
                        interval = null; //precaution
                        functionCall();

                    }
        //set width to compare on next interval after half a second
                    width = $(window).width();
                }, 500);

            }else{
                //logging that should be removed in production
                console.log("function call " + numi++ + " and inteval set skipped");

            }

}

0
ответ дан David Kamer 28 August 2018 в 21:16
поделиться

Internet Explorer предоставляет событие resizeEnd . Другие браузеры будут вызывать событие изменения размера много раз, пока вы изменяете размер.

Здесь есть другие отличные ответы, которые показывают, как использовать setTimeout и .throttle , . debounce из lodash и подчеркивания, поэтому я расскажу о плагине jQuery с дроссельной заслонкой Бен Альмана, который выполняет то, что вам нужно.

Предположим, что у вас есть эта функция, вы хотите вызвать после изменения размера:

function onResize() {
  console.log("Resize just happened!");
};

Пример дроссельной заслонки В следующем примере onResize() вызывается только один раз каждые 250 миллисекунд во время изменения размера окна.

$(window).resize( $.throttle( 250, onResize) );

Пример отладки В следующем примере onResize() будет вызываться только один раз в конце действия изменения размера окна. Это дает тот же результат, который @Mark представляет в своем ответе.

$(window).resize( $.debounce( 250, onResize) );
33
ответ дан falsarella 28 August 2018 в 21:16
поделиться
var resizeTimer;
$( window ).resize(function() {
    if(resizeTimer){
        clearTimeout(resizeTimer);
    }
    resizeTimer = setTimeout(function() {
        //your code here
        resizeTimer = null;
        }, 200);
    });

Это работало на то, что я пытался сделать в хроме. Это не вызовет обратный вызов до 200 мс после последнего изменения размера.

0
ответ дан frost287 28 August 2018 в 21:16
поделиться

Ответ Марка Колемана, безусловно, намного лучше, чем выбранный ответ, но если вы хотите избежать глобальной переменной для идентификатора тайм-аута (переменная doit в ответе Марка), вы можете сделать одно из следующего:

(1) Для создания замыкания используйте выражение, вызванное немедленно вызываемым (IIFE).

$(window).resize((function() { // This function is immediately invoked
                               // and returns the closure function.
    var timeoutId;
    return function() {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function() {
            timeoutId = null; // You could leave this line out.
            // Code to execute on resize goes here.
        }, 100);
    };
})());

(2) Используйте свойство функции обработчика событий.

$(window).resize(function() {
    var thisFunction = arguments.callee;
    clearTimeout(thisFunction.timeoutId);
    thisFunction.timeoutId = setTimeout(function() {
        thisFunction.timeoutId = null; // You could leave this line out.
        // Code to execute on resize goes here.
    }, 100);
});
1
ответ дан John S 28 August 2018 в 21:16
поделиться

Одним из решений является расширение jQuery с помощью функции, например: resized

$.fn.resized = function (callback, timeout) {
    $(this).resize(function () {
        var $this = $(this);
        if ($this.data('resizeTimeout')) {
            clearTimeout($this.data('resizeTimeout'));
        }
        $this.data('resizeTimeout', setTimeout(callback, timeout));
    });
};

Использование образца:

$(window).resized(myHandler, 300);

5
ответ дан Jone Polvora 28 August 2018 в 21:16
поделиться

Существует элегантное решение, использующее Underscore.js Итак, если вы используете его в своем проекте, вы можете сделать следующее -

$( window ).resize( _.debounce( resizedw, 500 ) );

должно быть достаточно :) Но, если вам интересно узнать больше об этом, вы можете проверить мой пост в блоге - http://rifatnabi.com/post/detect-end-of-jquery-resize-event-using -underscore-дребезг (DeadLink)

22
ответ дан mickmackusa 28 August 2018 в 21:16
поделиться

Здесь ОЧЕНЬ простой скрипт для запуска события «resizestart» и «resizeend» на объекте window.

Нет необходимости гадать с датами и временем.

] Переменная d представляет количество миллисекунд между событиями изменения размера перед запуском события окончания изменения размера, вы можете играть с этим, чтобы изменить, насколько чувствительным является конечное событие.

Чтобы прослушать эти события, все, что вам нужно сделать:

resizestart: $(window).on('resizestart', function(event){console.log('Resize Start!');});

resizeend: $(window).on('resizeend', function(event){console.log('Resize End!');});

(function ($) {
    var d = 250, t = null, e = null, h, r = false;

    h = function () {
        r = false;
        $(window).trigger('resizeend', e);
    };

    $(window).on('resize', function (event) {
        e = event || e;
        clearTimeout(t);

        if (!r) {
            $(window).trigger('resizestart', e);
            r = true;
        }

        t = setTimeout(h, d);
    });
}(jQuery));
1
ответ дан Neaox 28 August 2018 в 21:16
поделиться

Это код, который я пишу в соответствии с ответом @Mark Coleman:

$(window).resize(function() {
    clearTimeout(window.resizedFinished);
    window.resizedFinished = setTimeout(function(){
        console.log('Resized finished.');
    }, 250);
});

Спасибо, Марк!

67
ответ дан Roy Shoa 28 August 2018 в 21:16
поделиться

Я не знаю, работает ли мой код для других, но для меня это действительно отличная работа. Я получил эту идею, проанализировав код Долана Антенуччи, потому что его версия не работает для меня, и я действительно надеюсь, что это будет полезно кому-то.

var tranStatus = false;
$(window).resizeend(200, function(){
    $(".cat-name, .category").removeAttr("style");
    //clearTimeout(homeResize);
    $("*").one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",function(event) {
      tranStatus = true;
    });
    processResize();
});

function processResize(){
  homeResize = setInterval(function(){
    if(tranStatus===false){
        console.log("not yet");
        $("*").one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",function(event) {
            tranStatus = true;
        }); 
    }else{
        text_height();
        clearInterval(homeResize);
    }
  },200);
}
0
ответ дан Sai Pone Tha Aung 28 August 2018 в 21:16
поделиться

Это модификация кода Долана выше, я добавил функцию, которая проверяет размер окна в начале изменения размера и сравнивает его с размером в конце изменения размера, если размер больше или меньше (например, 1000), то он перезагружается.

var rtime = new Date(1, 1, 2000, 12,00,00);
var timeout = false;
var delta = 200;
var windowsize = $window.width();
var windowsizeInitial = $window.width();

$(window).on('resize',function() {
    windowsize = $window.width();
    rtime = new Date();
    if (timeout === false) {
            timeout = true;
            setTimeout(resizeend, delta);
        }
});

function resizeend() {
if (new Date() - rtime < delta) {
    setTimeout(resizeend, delta);
    return false;
} else {
        if (windowsizeInitial > 1000 && windowsize > 1000 ) {
            setTimeout(resizeend, delta);
            return false;
        }
        if (windowsizeInitial < 1001 && windowsize < 1001 ) {
            setTimeout(resizeend, delta);
            return false;
        } else {
            timeout = false;
            location.reload();
        }
    }
    windowsizeInitial = $window.width();
    return false;
}
2
ответ дан Sami A. 28 August 2018 в 21:16
поделиться
(function(){
    var special = jQuery.event.special,
        uid1 = 'D' + (+new Date()),
        uid2 = 'D' + (+new Date() + 1);

    special.resizestart = {
        setup: function() {
            var timer,
                handler =  function(evt) {
                    var _self = this,
                        _args = arguments;
                    if (timer) {
                        clearTimeout(timer);
                    } else {
                        evt.type = 'resizestart';
                        jQuery.event.handle.apply(_self, _args);
                    }

                    timer = setTimeout( function(){
                        timer = null;
                    }, special.resizestop.latency);
                };
            jQuery(this).bind('resize', handler).data(uid1, handler);
        },
        teardown: function(){
            jQuery(this).unbind( 'resize', jQuery(this).data(uid1) );
        }
    };

    special.resizestop = {
        latency: 200,
        setup: function() {
            var timer,
                handler = function(evt) {
                    var _self = this,
                        _args = arguments;
                    if (timer) {
                        clearTimeout(timer);
                    }
                    timer = setTimeout( function(){
                        timer = null;
                        evt.type = 'resizestop';
                        jQuery.event.handle.apply(_self, _args);
                    }, special.resizestop.latency);
                };

            jQuery(this).bind('resize', handler).data(uid2, handler);
        },
        teardown: function() {
            jQuery(this).unbind( 'resize', jQuery(this).data(uid2) );
        }
    };
})();

$(window).bind('resizestop',function(){
    //...
});
1
ответ дан Shadow Wizard 28 August 2018 в 21:16
поделиться

Я написал функцию-оболочку litte самостоятельно ...

onResize  =   function(fn) {
    if(!fn || typeof fn != 'function')
        return 0;

    var args    = Array.prototype.slice.call(arguments, 1);

    onResize.fnArr    = onResize.fnArr || [];
    onResize.fnArr.push([fn, args]);

    onResize.loop   = function() {
        $.each(onResize.fnArr, function(index, fnWithArgs) {
            fnWithArgs[0].apply(undefined, fnWithArgs[1]);
        });
    };

    $(window).on('resize', function(e) {
        window.clearTimeout(onResize.timeout);
        onResize.timeout    = window.setTimeout("onResize.loop();", 300);
    });
};

Вот использование:

var testFn  = function(arg1, arg2) {
    console.log('[testFn] arg1: '+arg1);
    console.log('[testFn] arg2: '+arg2);
};

// document ready
$(function() {
    onResize(testFn, 'argument1', 'argument2');
});
1
ответ дан user2123506 28 August 2018 в 21:16
поделиться

ResizeStart и события ResizeEnd для окна

http://jsfiddle.net/04fLy8t4/

Я реализовал функцию, которая запускает два события в пользовательском элементе DOM:

  1. resizestart
  2. resizeend

Код:

var resizeEventsTrigger = (function () {
    function triggerResizeStart($el) {
        $el.trigger('resizestart');
        isStart = !isStart;
    }

    function triggerResizeEnd($el) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(function () {
            $el.trigger('resizeend');
            isStart = !isStart;
        }, delay);
    }

    var isStart = true;
    var delay = 200;
    var timeoutId;

    return function ($el) {
        isStart ? triggerResizeStart($el) : triggerResizeEnd($el);
    };

})();

$("#my").on('resizestart', function () {
    console.log('resize start');
});
$("#my").on('resizeend', function () {
    console.log('resize end');
});

window.onresize = function () {
    resizeEventsTrigger( $("#my") );
};
0
ответ дан WebBrother 28 August 2018 в 21:16
поделиться

Вы можете использовать setTimeout() и clearTimeout() в сочетании с jQuery.data :

$(window).resize(function() {
    clearTimeout($.data(this, 'resizeTimer'));
    $.data(this, 'resizeTimer', setTimeout(function() {
        //do something
        alert("Haven't resized in 200ms!");
    }, 200));
});

Обновить

Я написал extension , чтобы улучшить jQuery по умолчанию on (& amp; bind) - обработчик событий. Он прикрепляет функцию обработчика событий для одного или нескольких событий к выбранным элементам, если событие не было инициировано для заданного интервала. Это полезно, если вы хотите активировать обратный вызов только после задержки, например событие изменения размера или другое. https://github.com/yckart/jquery.unevent.js

;(function ($) {
    var methods = { on: $.fn.on, bind: $.fn.bind };
    $.each(methods, function(k){
        $.fn[k] = function () {
            var args = [].slice.call(arguments),
                delay = args.pop(),
                fn = args.pop(),
                timer;

            args.push(function () {
                var self = this,
                    arg = arguments;
                clearTimeout(timer);
                timer = setTimeout(function(){
                    fn.apply(self, [].slice.call(arg));
                }, delay);
            });

            return methods[k].apply(this, isNaN(delay) ? arguments : args);
        };
    });
}(jQuery));

Используйте его, как и любой другой обработчик on или bind -event, за исключением того, что вы можете передать дополнительный параметр последнему:

$(window).on('resize', function(e) {
    console.log(e.type + '-event was 200ms not triggered');
}, 200);

http://jsfiddle.net/ARTsinn/EqqHx/

3
ответ дан yckart 28 August 2018 в 21:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: