2010-03-08 13 views
15

Tôi cần có nhiều trang bằng AJAX và đặt chúng vào một mảng, trong đó vị trí đã cho của chúng trong mảng bằng i của vòng lặp for (đó là một chức năng giống như bộ nhớ đệm cho các trang blog, và phạm vi của vòng lặp for là hoàn toàn biến). Tôi đang làm một cái gì đó tương tự như sau:Gọi AJAX cho vòng lặp sẽ không trả về giá trị để sửa các vị trí mảng

var bongo = new Array(); 

for (i = 0; i < 10; i++) { 

    jQuery.ajax({ type: "GET", url: 'http://localhost', data: queryString, success: function(request) { bongo[i] = request } }) 

} 

Vấn đề là, rằng trừ khi tôi thêm async: false với các tùy chọn .ajax (mà sẽ làm cho nó ... SJAX?), Gây ra các yêu cầu cơ bản tạm dừng trình duyệt, chống lại những gì tôi đang cố gắng thực hiện, i trong cuộc gọi lại thành công sẽ luôn kết thúc là 11, trong khi tôi tất nhiên muốn nó đổ dữ liệu được trả về vào mỗi khe của mảng từ 0 đến 10.

Tôi đã thử thay thế đường dây bằng cách này:

bongo[i] = jQuery.ajax({ type: "GET", url: 'http://localhost', data: queryString }).responseText 

Nhưng điều đó không có gì khác biệt.

Trả lời

38

Bạn cần một đóng cửa:

var bongo = []; 
for (i = 0; i < 10; i++) 
{ 

    (function(i) 
    { 
     jQuery.ajax(
     { 
      type: "GET", 
      url: "http://localhost", 
      data: queryString, 
      success: function(request) { bongo[i] = request } 
     }); 
    })(i); 
} 

Loops là # 1 nơi mà chức năng inline Stump người. Các bongo[i] = result không được gọi cho đến sau này. Giá trị của i tại thời điểm đó là khác nhau (rất có thể là 11). Nếu bạn muốn "bẫy" hoặc "bắt giữ" hiện tại giá trị của i, bạn cần tạo phạm vi mới. Cách duy nhất để làm điều đó trong javascript là với một chức năng khác.

+0

Nó hoạt động như một sự quyến rũ. Nhưng tôi đã không có được những gì cuối cùng (i), ai đó có thể giải thích điều đó? –

+0

giá trị của bên ngoài i được chuyển vào chức năng ẩn danh tự thực hiện gói; vị trí của giá trị duy nhất này được ghi lại bằng cách gọi lại không đồng bộ. Theo cách này, mỗi async nhận giá trị riêng của nó, được xác định tại thời điểm hàm tự thực hiện được gọi. Đó là điểm đóng cửa !! ;) – Plastic

4

Hãy thử:

var bongo = []; 
for (i=0; i<10; i++) { 
    $.get("http://localhost", function(result) { 
    bongo.push(result); 
    } 
} 

Bằng cách này mỗi kết quả đơn giản sẽ được đẩy lên mảng, giải quyết nhu cầu về các chỉ số mảng là đúng. Tuy nhiên, đơn đặt hàng không được bảo đảm. Nếu đó là một yêu cầu bạn sẽ cần một cách tiếp cận khác.

Có nhiều cách để giải quyết vấn đề này. Đây là một: tạo các đối tượng để gọi lại của bạn để lưu trạng thái. Dưới đây là một ví dụ:

function Callback(array, index, result) { 
    this.array = array; 
    this.index = index; 
    this.result = result; 
    var obj = this; 
    this.func = function() { 
    obj.array[obj.index] = obj.result; 
    }; 
} 

$(function() { 
    var arr = []; 
    for (var i=0; i<4; i++) { 
    var obj = new Callback(arr, i, "result" + i); 
    setTimeout(obj.func, (5-i) * 100); 
    } 
    setTimeout(function() { 
    console.log(arr); 
    }, 500); 
}); 

Vì vậy, trong trường hợp của bạn:

function Callback(array, index) { 
    this.array = array; 
    this.index = index; 
    var obj = this; 
    this.callback = function(result) { 
    obj.array[obj.index] = result; 
    }; 
} 

var bongo = []; 
for (i=0; i<10; i++) { 
    var ob = new Callback(bongo, i); 
    $.get("http://localhost", ob.callback); 
} 

Về cơ bản các tiết kiệm trên tất cả các dữ liệu vào một đối tượng và do đó mỗi callback có quyền truy cập vào các thông tin chính xác.

Ngoài ra, hãy nhớ rằng hầu hết các trình duyệt giới hạn số lượng yêu cầu AJAX đồng thời, thường là 2 cho mỗi máy chủ.

+0

Nhưng bằng cách này tôi không thể quyết định chính xác vị trí nào trong mảng dữ liệu được đẩy tới, đó là những gì tôi cần. – Heilemann

+0

@Heilemann đã thêm phiên bản giúp lưu chỉ mục theo đúng thứ tự. – cletus

Các vấn đề liên quan