2014-12-10 3 views
1

У меня есть следующий код с Angular.js:JavaScript/сохранить значения переменных с обратным вызовом

$scope.createSSH = function(){ 
      for (var j=0; j<allGroupsArrays.length; j++){ 
       for (var i=0; i<$scope.appArray.length; i++){ 
        allGroupsArrays[j][i][6] = Boolean(0); 
        allGroupsArrays[j][i][7] = Boolean(0); 
        // Some irrelvant code 
        WClient.createSSHK(allGroupsArrays[j][i][2], allGroupsArrays[j][i][3], allGroupsArrays[j][i][4], i, allGroupsArrays[j], allGroupsArrays[j][i][7], j).then(
       function(data) { 
        console.log("The j is: " + j) 
        console.log("The i is: " + i) 
        }, 
       function(message) { 
        console.log("Error") 
        } 

Когда обратный вызов поддерживаются, я замечаю, что значение j и i переменных было банкнота сохранить. Вместо этого, он печатает следующее:

The j is: 5 
The i is: 3 

Они даже тогда, когда обратный вызов был выполнен было i 0 и j был 0.

Как сохранить значение контекста переменного?

+0

Это правильно. Вы всегда будете получать эти значения. Это потому, что во время выполнения цикла обратный вызов не будет вызван до создания createSSHK. Помните, что это асинхронно. Вам может потребоваться передать эту переменную для создания SSHK, а затем принять ее в обратном вызове. –

ответ

0

Это типичная проблема закрытия. Петли выполняются и после того, как они являются полными значениями i и j, являются 5 и 3 конечно. Однако then функции обратного вызова по-прежнему используют значения i и j из внешней области. Что вам нужно сделать, так это создать отдельные значения области.

Один из способов сделать это (и есть как минимум 6 способов!) Использует метод функции Function.prototype.bind. Это работает, потому что он создает новую функцию с контекстными значениями для i и j:

WClient.createSSHK(allGroupsArrays[j][i][2], allGroupsArrays[j][i][3], allGroupsArrays[j][i][4], i, allGroupsArrays[j], allGroupsArrays[j][i][7], j).then(
    function(i, j, data) { 
     console.log("The j is: " + j) 
     console.log("The i is: " + i) 
    }.bind(null, i, j), 

    function(message) { 
     console.log("Error") 
    }.bind(null, i, j) 
); 

Также обратите внимание на this очень популярный вопрос на ту же тему.

+0

Я думаю, вы имеете в виду Function.prototype.bind –

+0

@JoelJeske, конечно же, спасибо! – dfsq

+0

Обратите внимание: функция 'Function.prototype.bind' не будет работать в IE <9 – Zudwa

0

Когда функция обратного вызова называется, i и j значение взято из родительского контекста, и как они увеличиваются, значение всегда будет последним увеличиваются (5 и 3 соответственно). Чтобы преодолеть это, вы должны передать текущие значения, которые будут использоваться:

.then((function(i, j) { 
    return function(data) { 
     console.log("The j is: " + j) 
     console.log("The i is: " + i) 
    }; 
})(i, j)) 

Здесь вы создаете функцию приема текущих значений (function(i, j) {...}, вызвать его немедленно (i, j)) и с их независимыми от родительского контекста. Эта функция возвращает функцию, которая должна быть выполнена (return function(data) {...}). Теперь у вас есть data, переданный callback invoker, и ij имеют значения, переданные по вызову createSSHK.

0

Невозможно создать функции в цикле. Попробуйте что-то вроде этого:

$scope.createSSH = function(){ 
     for (var j=0; j<allGroupsArrays.length; j++){ 
      for (var i=0; i<$scope.appArray.length; i++){ 
       allGroupsArrays[j][i][6] = Boolean(0); 
       allGroupsArrays[j][i][7] = Boolean(0); 
       process(i ,j); 
      } 
     } 

function process(i, j){ 
       WClient.createSSHK(allGroupsArrays[j][i][2], allGroupsArrays[j][i][3], allGroupsArrays[j][i][4], i, allGroupsArrays[j], allGroupsArrays[j][i][7], j).then(
      function(data) { 
       console.log("The j is: " + j) 
       console.log("The i is: " + i) 
       }, 
      function(message) { 
       console.log("Error") 
       } 
} 
Смежные вопросы