【问题标题】:javascript/jquery leaking and crashing browserjavascript/jquery 泄漏和崩溃的浏览器
【发布时间】:2009-02-05 20:46:38
【问题描述】:

让我先说一下实际上是我的糟糕代码泄漏并导致我的浏览器崩溃,我只是想我最好从一开始就尽可能清楚地使用所使用的语言。

我有一个测试页面here,可以在here 找到javascript。我的问题是,当我尝试多次拖放任何一个红色块时,它会占用所有浏览器资源并使浏览器崩溃。我相当确定罪魁祸首是 Tracker() 对象中的以下函数,但我完全不知道如何调试它。

我目前最有可能的罪魁祸首:

  function register_draggable(ob) {
      ob.config.jqId.draggable({cursor: 'move',
                              grid:[ob.config.size, ob.config.size],
                              containment: '#chessboard',
                              revert: 'invalid',
                              start: function() {
                                check_allowable_moves(ob.config.jqLocation,
                                                      ob.config.jqId,
                                                      ob);
                              },
                              stop: function() {
                                remove_allowable_moves();
                              }
                            });
  }

如果有人可以快速浏览一下并就我应该寻找什么给我任何建议,我们将不胜感激。

解决方案 原来register_draggable() 是罪魁祸首。每次更新片段的位置并且同一对象上的所有那些可拖动对象都在做讨厌的事情时,我都会注册一个新的可拖动对象。 目前,我现在明确地在创建新的可拖动对象之前销毁旧的可拖动对象。当前代码是

    function register_draggable(ob) {
    ob.config.jqId.draggable('destroy');
    ob.config.jqId.draggable({cursor: 'move',
                              grid:[ob.config.size, ob.config.size],
                              containment: '#chessboard',
                              revert: 'invalid',
                              start: function() {
                                check_allowable_moves(ob.config.jqLocation, 
                                                      ob.config.jqId, 
                                                      ob);
                              },
                              stop: function() {
                                remove_allowable_moves();
                              }
                            });
  }

【问题讨论】:

  • 让 check_allowable_moves 立即返回,我猜它在里面。
  • 哇,是的,它 def 正在泄漏内存,或者它在 5 次移动后导致我的浏览器崩溃。我的猜测是 check_allowable_moves 也可能与它有关。
  • 在测试脚本中调用 check_allowable_moves,无需任何拖放操作。看看它的表现。
  • 我认为几乎可以肯定添加可拖动的次数太多了。如果我把 ob.config.jqId.draggable('destroy');作为 register_draggable(ob) 的第一行,它工作得更好
  • 这个好像很眼熟……

标签: javascript jquery debugging memory-leaks


【解决方案1】:

我认为这实际上不是您的问题,但您似乎对 register 和 check_allowable_moves 进行了额外的方法调用

return {
        register_map: function(ob) { map = ob; },
        register_piece: function(ob) {
          ob.config.tracker = this;
          register_draggable(ob);
        },
        register_draggable: function(ob) { register_draggable(ob); },
        check_allowable_moves: function(location, jqPiece, ob) { check_allowable_moves(location, jqPiece, ob); }
      }

可以缩短为

return {
        register_map: function(ob) { map = ob; },
        register_piece: function(ob) {
          ob.config.tracker = this;
          register_draggable(ob);
        },
        register_draggable: register_draggable,
        check_allowable_moves: check_allowable_moves
      }

还有

您在这里进行双重查找:

function remove_allowable_moves() {
        $('.allowable').droppable('destroy');
        $('.allowable').removeClass('allowable');
      }

应该是

function remove_allowable_moves() {
        $('.allowable').droppable('destroy')
          .removeClass('allowable');
      }

还有

将 int 解析为浮点数的目的是什么?去掉 parseFloat。

var x = parseInt(locs[1]);
var y = parseInt(locs[2]);
var x_min = parseFloat(x)-2;
var y_min = parseFloat(y)-2;

终于

为什么要重新注册为可拖放的?如果您多次注册可拖动对象并且只销毁一次,这可能是罪魁祸首。

jqCell.droppable({ accept: '#'+jqPiece.attr('id'),
                  drop: function(ev, ui) {
                    ob.config.jqLocation = $(this);
                    register_draggable(ob);  // why this?
                  }
                });

其他想法

另一件事我不知道它是否会帮助您提高性能,但它可以清理您的代码。 jquery 选择器允许使用逗号而不是

$('#coord-1-1').doStuff();
$('#coord-1-2').doStuff();
$('#coord-1-3').doStuff();

你可以的

$('#coord-1-1, #coord-1-2, #coord-1-3').doStuff();

所以你的循环只关心生成选择器字符串,然后你可以在整个集合上运行你的操作。

IMO 更清洁的初始化

而不是

var map = new Map('content');
var piece1 = new Piece(map);
var piece2 = new Piece(map);
var tracker = new Tracker;
tracker.register_map(map);
map.render();
piece1.render('coord-4-4', '1');
piece2.render('coord-1-1', '2');
tracker.register_piece(piece1);
tracker.register_piece(piece2);

我想看看

$(document).ready(function() {
    $('#content').MapGame({
        pieces : { '1' : 'coord-4-4', '2' : 'coord-1-1' }
    });
});

现在实现它是你现在所拥有的一个延伸,但是在为 jQuery 构建组件时,我喜欢从一个简单的 init 开始并从它们开始工作。 jQuery 的一大目标就是向用户隐藏所有垃圾,让他们轻松启动插件实例。

【讨论】:

  • 好的,链接和 parseFloat 删除工作很好,只是这段代码的早期迭代留下了一些代码草率。方法调用的缩短使允许的移动类停止工作,所以我把它们放回去了。
  • 我不止一次注册可拖动对象,因为每次移动都需要更新它的新位置。不过你是对的,这肯定是罪魁祸首。我在每次创建新的可拖动对象之前销毁了旧的可拖动对象,这很有帮助。
  • 太好了,我很高兴有帮助,那么我们在哪里?
  • 不缩短方法调用还有其他原因。我从来没有见过用这样的方法返回一个新对象的技术。如果您真的想坚持 jQuery 指导方针,您可能需要查看 docs.jquery.com/Plugins/Authoring
  • 我只是要留下代码来销毁可拖动对象,然后再在那里重新创建它,然后转到另一个问题。感觉有点像 hack,但目前我只想在我回去找出更好的方法做所有事情之前启动并运行这个想法的工作原型。
【解决方案2】:

感觉有些事件处理程序被注册了多次,但我不确定。 (原因如下。)


这并不能回答问题,但您绝对应该在$(document).ready(…) 之外放置尽可能多的代码,决不能像现在这样将所有代码都放在那里。

我担心您的代码太不合格,以至于理解它的工作量太大。你能重组它吗(所有那些函数中的函数真的很难读。)并添加一些 cmets。

也许只有我一个人,但我觉得它太难阅读和理解了。维护它肯定会是一场灾难。

【讨论】:

猜你喜欢
  • 2016-07-14
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 2014-04-17
  • 2018-08-06
相关资源
最近更新 更多