setInterval с другими событиями jQuery - слишком много рекурсий - PullRequest
1 голос
/ 12 июля 2010

Я пытаюсь создать слушатель Javascript для маленькой страницы, которая использует AJAX для загрузки контента на основе привязки в URL. Посмотрев в Интернете, я нашел и изменил скрипт, который использует setInterval() для этого, и пока он работает нормально. Тем не менее, у меня есть другие элементы jQuery в $(document).ready() для специальных эффектов для меню и контента. Если я использую setInterval(), другие jQuery-эффекты не работают. Я нашел способ заставить его работать, включив эффекты jQuery в цикл для setInterval() примерно так:

$(document).ready(function() {
    var pageScripts = function() {
        pageEffects();
        pageURL();      
    }
    window.setInterval(pageScripts, 500);
});

var currentAnchor = null;

function pageEffects() {
    // Popup Menus
    $(".bannerMenu").hover(function() {
        $(this).find("ul.bannerSubmenu").slideDown(300).show;
    }, function() {
        $(this).find("ul.bannerSubmenu").slideUp(400);
    });

    $(".panel").hover(function() {
        $(this).find(".panelContent").fadeIn(200);
    }, function() {
        $(this).find(".panelContent").fadeOut(300);
    });

    // REL Links Control
    $("a[rel='_blank']").click(function() {
        this.target = "_blank";
    });
    $("a[rel='share']").click(function(event) {
        var share_url = $(this).attr("href");

        window.open(share_url, "Share", "width=768, height=450");
        event.preventDefault();
    });
}

function pageURL() {
    if (currentAnchor != document.location.hash) {
        currentAnchor = document.location.hash;
        if (!currentAnchor) {
            query = "section=home";
        } else {
            var splits = currentAnchor.substring(1).split("&");
            var section = splits[0];
            delete splits[0];
            var params = splits.join("&");
            var query = "section=" + section + params;
        }
        $.get("loader.php", query, function(data) {
            $("#load").fadeIn("fast");
            $("#content").fadeOut(100).html(data).fadeIn(500);  
            $("#load").fadeOut("fast");
        });
    }
}

Некоторое время это работает нормально, но через несколько минут после загрузки страницы она почти останавливается в IE и Firefox. Я проверил консоль ошибок FF, и она возвращается с ошибкой «Слишком много рекурсий». Chrome, кажется, не заботится, и страница продолжает работать более или менее нормально, несмотря на то, сколько времени она открыта.

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

Любая помощь по этому вопросу будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 14 июля 2010

Спасибо за предложения. Я попробовал несколько из них, и они все еще не привели к желаемым эффектам. После некоторого осторожного тестирования я узнал, что происходит. С помощью jQuery (и, по-видимому, Javascript в целом) всякий раз, когда выполняется обратный вызов AJAX, элементы, введенные посредством обратного вызова, не привязываются к тому, что изначально было связано в документе, они должны быть повторно привязаны. Вы можете сделать это, вызвав все события jQuery при успешном обратном вызове, или используя событие .live() в библиотеке jQuery. Я выбрал .live(), и теперь он работает, как талисман, и больше никаких рекурсивных ошибок: D.

    $(document).ready(function() {
    // Popup Menus
    $(".bannerMenu").live("hover", function(event) {
        if (event.type == "mouseover") {
            $(this).find("ul.bannerSubmenu").slideDown(300);
        } else {
            $(this).find("ul.bannerSubmenu").slideUp(400);
        }
    });

    // Rollover Content
    $(".panel").live("hover", function(event) {
        if (event.type == "mouseover") {
            $(this).find(".panelContent").fadeIn(200);
        } else {
            $(this).find(".panelContent").fadeOut(300);
        }
    });

    // HREF Events
    $("a[rel='_blank']").live("click", function(event) {
        var target = $(this).attr("href");
        window.open(target, "_blank");
        event.preventDefault();
    });

    $("a[rel='share']").live("click", function(event) {
        var share_url = $(this).attr("href");
        window.open(share_url, "Share", "width=768, height=450");
        event.preventDefault();
    });

    setInterval("checkAnchor()", 500);
});

var currentAnchor = null;

function checkAnchor() {
    if (currentAnchor != document.location.hash) {
        currentAnchor = document.location.hash;
        if (!currentAnchor) {
            query = "section=home";
        } else {
            var splits = currentAnchor.substring(1).split("&");
            var section = splits[0];
            delete splits[0];
            var params = splits.join("&");
            var query = "section=" + section + params;
        }
        $.get("loader.php", query, function(data) {
            $("#load").fadeIn(200);
            $("#content").fadeOut(200).html(data).fadeIn(200);
            $("#load").fadeOut(200);
        });
    }
}

Так или иначе, страница работает так, как задумано, даже в IE (который я редко проверяю на совместимость). Будем надеяться, что некоторые другие новички будут учиться на моих ошибках: p.

0 голосов
/ 12 июля 2010

Я предполагаю, что pageEffects необходимо добавить к содержимому pageURL.

По крайней мере это должно быть более эффективным и предотвращать дублирование обработчиков

$(document).ready(function() {
   pageEffects($('body'));
   (function(){
       pageURL(); 
       window.setTimeout(arguments.callee, 500);
   })();              
});

var currentAnchor = null;

function pageEffects(parent) {
    // Popup Menus
    parent.find(".bannerMenu").each(function() {
        $(this).unbind('mouseenter mouseleave');
        var proxy = {
            subMenu: $(this).find("ul.bannerSubmenu"),
            handlerIn: function() {
              this.subMenu.slideDown(300).show();
            },
            handlerOut: function() {
              this.subMenu.slideUp(400).hide();
            }
        };
        $(this).hover(proxy.handlerIn, proxy.handlerOut);
    });

    parent.find(".panel").each(function() {
        $(this).unbind('mouseenter mouseleave');
        var proxy = {
          content: panel.find(".panelContent"),
          handlerIn: function() {
            this.content.fadeIn(200).show();
          },
          handlerOut: function() {
            this.content.slideUp(400).hide();
          }
        };
        $(this).hover(proxy.handlerIn, proxy.handlerOut);
    });

    // REL Links Control
    parent.find("a[rel='_blank']").each(function() {
        $(this).target = "_blank";
    });

    parent.find("a[rel='share']").click(function(event) {
        var share_url = $(this).attr("href");

        window.open(share_url, "Share", "width=768, height=450");
        event.preventDefault();
    });
}

function pageURL() {
    if (currentAnchor != document.location.hash) {
        currentAnchor = document.location.hash;
        if (!currentAnchor) {
            query = "section=home";
        } else {
            var splits = currentAnchor.substring(1).split("&");
            var section = splits[0];
            delete splits[0];
            var params = splits.join("&");
            var query = "section=" + section + params;
        }
        var content = $("#content");
        $.get("loader.php", query, function(data) {
            $("#load").fadeIn("fast");
            content.fadeOut(100).html(data).fadeIn(500);  
            $("#load").fadeOut("fast");
        });

        pageEffects(content);
    }
}
...