2011-08-13 24 views
53

Hãy nói rằng tôi có một cái gì đó như sau:Khi sử dụng cuộc gọi lại bên trong một vòng lặp trong javascript, có cách nào để lưu biến được cập nhật trong vòng lặp để sử dụng trong cuộc gọi lại không?

for(var i = 0; i < length; i++){ 
    var variable = variables[i]; 
    otherVariable.doSomething(variable, function(err){ //callback for when doSomething ends 
    do something else with variable; 
    } 

Vào thời điểm callbacks được gọi là, variable chắc chắn sẽ biến cuối cùng cho tất cả các callbacks, thay vì là một khác nhau cho mỗi cuộc gọi lại, như tôi sẽ như. Tôi nhận ra rằng tôi có thể vượt qua variable để doSomething() và sau đó nhận được rằng trở lại như một phần của cuộc gọi lại, nhưng doSomething() là một phần của một thư viện bên ngoài, và tôi không muốn lộn xộn xung quanh với mã nguồn cho điều đó.

Làm những người bạn biết JavaScript tốt hơn tôi biết liệu có cách nào khác để làm những gì tôi muốn làm không?

nhất, và cảm ơn,
Sami

Trả lời

41

Một thông thường, nếu xấu xí, cách đối phó với tình trạng này là sử dụng một chức năng mà ngay lập tức được viện dẫn để tạo ra một phạm vi để giữ biến.

for(var i = 0; i < length; i++) { 
    var variable = variables[i]; 
    otherVariable.doSomething(function(v) { return function(err) { /* something with v */ }; }(variable)); 
} 

ý rằng bên trong hàm ngay lập tức gọi gọi lại đang được tạo ra, và trở về, tham chiếu các tham số cho hàm v và không phải là bên ngoài variable. Để làm cho việc đọc này tốt hơn nhiều, tôi khuyên bạn nên giải nén hàm tạo của hàm gọi lại làm hàm được đặt tên.

function callbackFor(v) { 
    return function(err) { /* something with v */ }; 
} 
for(var i = 0; i < length; i++) { 
    var variable = variables[i]; 
    otherVariable.doSomething(callbackFor(variable)); 
} 
+0

Thật không may, điều này không hữu ích trong trường hợp của tôi vì doSomething() là một hàm từ thư viện mà tôi không muốn chỉnh sửa. Khi thư viện này được cập nhật, tôi sẽ phải giữ lại mã nguồn và đó là điều mà tôi không muốn giải quyết. Giả sử tôi không thể thay đổi hàm doSomething(), tôi có thể làm gì không? – thisissami

+0

Điều này không yêu cầu bất kỳ thay đổi nào đối với 'doSomething()'. Tôi giả định rằng 'doSomething' chỉ đơn giản là lấy một cuộc gọi lại và rằng sự bao gồm tham số' biến' là thứ mà bạn có thể đang đề xuất thay đổi. Nếu chữ ký của 'doSomething' là' doSomething (val, callback) 'thì chỉ cần sửa đổi ví dụ của tôi thành' otherVariable.doSomething (biến, callbackFor (biến)) '. Điều quan trọng là một phạm vi mới được tạo ra, bằng cách gọi một hàm, để giữ giá trị của 'biến' cho hàm gọi lại. – aparker42

+0

Hmm vì vậy tôi đoán tôi hơi bối rối. Cách 'doSomething()' hoạt động là nó truyền biến, và sau đó 'doSomething()' sẽ gọi hàm callback được chỉ định, trong đó tham số đầu tiên là bất kỳ mã lỗi tiềm năng nào xuất phát từ 'doSomething()'. Nếu tôi đặt một wrapper 'function (variable)' quanh callback để tạo một scope mới, không phải 'function (variable)' trở thành callback thay vào đó, và tham số 'variable' thực sự là thông báo lỗi? – thisissami

31

Ok tôi dường như đã tìm ra điều này. Những gì tôi cần làm là đặt một wrapper function(var) xung quanh otherVariable.doSomething(), vì vậy mã được cập nhật trông như sau:

for(var i = 0; i < length; i++){ 
    var variable = variables[i]; 
    (function(var){ //start wrapper code 
    otherVariable.doSomething(var, function(err){ //callback for when doSomething ends 
     do something else with var; //please note that i'm dealing with var here, not variable 
    } 
    })(variable);//passing in variable to var here 
} 

hy vọng điều này giúp bất cứ ai khác mà bị mắc kẹt trên một cái gì đó như thế này trong tương lai!

@ aparker42, tôi vẫn muốn nghe câu trả lời của bạn cho câu hỏi của tôi trong nhận xét cho câu hỏi của bạn, vì điều đó vẫn làm tôi bối rối.

EDIT: tất nhiên, vì đây là javascript, bạn sẽ không muốn sử dụng var làm tên biến.

+3

Vâng, đây là bản chất giống như câu trả lời của tôi.Sự khác biệt là bạn sử dụng hàm được gọi ngay lập tức để tạo ra một phạm vi mà bạn thực hiện cuộc gọi đến 'doSomething'. Câu trả lời của tôi vừa tạo ra cuộc gọi lại trong phạm vi đó và sau đó trả về nó. Cuối cùng cả hai đều đạt được điều tương tự. – aparker42

+0

Để hỗ trợ và làm rõ, có, đây là câu trả lời tương tự mà aparker42 đặt, chỉ ở định dạng khác. Gọi lại trong trường hợp đó không được CALLED bởi doSomething, nó ngay lập tức trả về một giá trị. – dudewad

+14

Có lẽ không phải là một ý tưởng tốt để có một định danh có tên 'var' trong JavaScript. – danijar

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