2013-12-15 71 views
-1

我想检查许多项目与Ajax网址上的信息。但是,当我在浏览器中运行此功能时,内存使用率高于2个演出,然后浏览器崩溃(Chrome,Firefox)。我究竟做错了什么? items变量真的很大 - > 200 000,还包含一些大字符串。XMLHttpRequest循环内存泄漏

var items = [1,2,3,4,5,6,7,8,9,10,...,300000] 
var activeItems = {} 

function loopAjax(){ 
    for (i=0; i < items.length; i++) { 
     var currItem = items[i]; 
     var request = new XMLHttpRequest(); 
     var found = 0 

     request.open("GET", "/item=" + currItem); 
     request.onreadystatechange = function() { 
      if (request.readyState == 4 && request.status == 200) { 
       var response = JSON.parse(request.responseText); 
       var active = response[0].active; 
       if (active) { 
        console.log("FOUND ACTIVE! " + currItem); 
        activeItems[found] = {"active": true, "item": currItem}; 
        found++; 
       } 
      } 
     } 
     request.send(); 
    } 
} 
+2

... 300000是问题所在。你需要重新设计你如何解决这个问题 – robbmj

+4

这是一个可怕的设计。想想你在做什么。向服务器发出200,000个请求!?您没有任何延迟,因此您只需强制浏览器排队呼叫。没有休息。服务器应处理呼叫中的多个项目。不只是一个。您需要查看您的结尾电话排队。 – epascarello

+0

Woah,对服务器的请求太多了。为什么这么多要求? –

回答

2

谢天谢地浏览器崩溃并死亡。如果它不是你刚创建的拒绝服务攻击!

该问题需要重新考虑。你最好创建一个有一堆请求的状态机。这样你一次只能说5个并发请求。

function ItemChecker(sample_size, max_threads) { 
    this.sample_size = sample_size; 
    this.max_threads = max_threads; 
    this.counter = 0; 
    this.activeItems = []; 
    this.isRunning = false; 
    this.running_count = 0; 
} 

ItemChecker.prototype.start = function start() { 
    this.isRunning = true; 
    while (this.running_count < this.max_threads) { 
    this.next(); 
    } 
    return this; 
}; 

ItemChecker.prototype.stop = fucntion stop() { 
    this.isRunning = false; 
    return this; 
}; 

ItemChecker.prototype.next = function next() { 
    var request, item_id, _this = this; 

    function xhrFinished(req) { 
    var response; 
    if (req.readyState !== 4) { 
     return; 
    } 

    _this.counter--; 

    if (req.status === 200) { 
     try { 
     response = JSON.parse(request.responseText); 
     if (response[0].active) { 
      _this.activeItems.push({ 
      active: true, 
      item: item_id; 
      }); 
     } 
     } catch(e) { 
     console.error(e); 
     } 

     // When finished call a callback 
     if (_this.onDone && _this.counter >= _this.sample_size) { 
     _this.onDone(_this.activeItems); 
     } 
    } 
    else { 
     console.warn("Server returned " + req.status); 
    } 
    } 

    if (!this.isRunning || this.counter >= this.sample_size) { 
    return; 
    } 

    item_id = this.counter; 
    this.counter++; 

    request = new XMLHttpRequest(); 
    request.onreadystatechange = xhrFinished; 
    request.open("GET", "item=" + item_id); 
    request.send(); 
}; 

ItemChecker.prototype.whenDone = function whenDone(callback) { 
    this.onDone = callback; 
    return this; 
}; 

这可能有效吗?没有真正尝试过。但你可以这样称呼它:

var item_checker = new ItemChecker(300000, 5); 
item_checker.whenDone(function(active) { 
    // Do something with active 
}).start(); 
+0

当然,我会这样做的真实。我会用承诺来做。 – Sukima

+0

感谢您的回答。我发现了一种使用setTimeout限制并发请求的方法,但是这看起来更好,我会尝试一下。这是我自己的机器:) – Mark

+0

只是警告你,XMLHttpRequests是异步的,因为它是。将setTimeouts添加到逻辑只会使复杂性变得更糟。 – Sukima