2013-04-30 2 views
3

В следующем фрагменте кода есть ошибка, но он открыл интересный вопрос. Его использование угловой $ http службы, которая возвращает обещание. После разрешения функция обратного вызова не имеет доступа к переменной s1.функция обратного вызова доступа к переменным замыкания?

var ids = []; 
    ids = ['81074']; 

    // show what's in 
    for (var s=0;s<ids.length;s++) { 
     var s1 = s; 
     $http.get('http://mydomain.com/api/catalog/product/' + ids[s]). 
       success(function(data) { 
     // console.log(s1); <--- reference error 
      $scope.products[s].setProductData(data); 

     }).error(function(err){ 
       console.log('--------- error',err); 
      }); 
    }; 

s1 дает ReferenceError: s1 не определено в отладчике

И что интересно, у него есть доступ к для цикла переменной s, которая всегда 1 - как и следовало ожидать, так как обещание получил решен после того, как его прирост (отсюда ошибка BTW)

Может кто-нибудь объяснить, почему?

благодаря

Лиор

+1

Я не вижу никакого использования 's1', где происходит ошибка? – Barmar

+0

Ваш код не ссылается на s1 нигде после его определения. Как вы можете получить ссылочную ошибку? – KevSheedy

+0

Я проверил s1 в отладчике, а внутри обратного вызова. код отредактирован. спасибо за замечания – Lior

ответ

9

Это классическая проблема с асинхронными в for цикле. Оба s и s1 объявляются только один раз. Несмотря на то, что в цикле вы объявляете var s1;, JavaScript не имеет границ блока, поэтому он не имеет значения.

Это означает, что все итерации одни и те же переменные s и s1, поэтому, когда обратный вызов завершается, $scope.products[s] смотрит вверх ids.length + 1 продукт.

Вместо этого сделать:

var ids = []; 
ids = ['81074']; 

function launchRequest(s) { 
    $http.get('http://example.com/api/catalog/product/' + ids[s]).success(function (data) { 
     $scope.products[s].setProductData(data); 
    }).error(function (err) { 
     console.log('--------- error', err); 
    }); 
} 

// show what's in 
for (var s = 0; s < ids.length; s++) { 
    launchRequest(s); 
} 

... который вводит новую область уровня функции внутри launchRequest, что означает s еще s внутри функции обратного вызова, когда рассасывается.

+0

спасибо @Matt, я понимаю о s, и спасибо за ваше предложение! (Принято). Тем не менее, в исходном коде, почему s1 не отображается внутри обратного вызова? что я должен сделать, чтобы получить видимость s1? – Lior

+0

ОК - понял. извините - моя ошибка. s1 отображается, если вы его явно пишете. – Lior

Смежные вопросы