2013-10-24 6 views
0

При работе над программированием nodejs я нашел простую, но интересную проблему.
Чтобы выполнить очередь асинхронных функций по очереди, я обычно использую «массив заданий» с async.series.

следующих шагов:

1. Определяет массив
2. Функции Нажмите работу в массив.
3. Используя async.series, выполните его последовательно.
, например. async.series (jobFunctionList, callback);
Закрытие JavaScript - странная справочная функция анонимной функции, нажатой в Array

Следующий примерный код упрощен.
Описанный в комментарии, он не работает так, как я ожидал.

Переменные 'key' и 'value' изменяются
, даже после того, как функция Job определена и введена в массив jobList.

Кажется, что нажатая функция постоянно ссылается на внешнюю переменную,
не значение созданного обстоятельства.


Я нашел решение проблемы, но не знаю, почему это работает.

var dataList = { key1: 'value1', key2: 'value2' }; 

var jobList = new Array(); 

for (var key in dataList) 
{ 
    var value = dataList[key]; 

    jobList.push(
     function (next) 
     { 
      console.log(key + ' : ' + value); 
     } 
    ); 
} 

(jobList[0])(); 
(jobList[1])(); 

/* Expected Output : 

key1 : value1 
key2 : value2 

*/ 

/* Real Output : 

key2 : value2 <--- WHY ??? 
key2 : value2 

*/ 

ответ

2

Анонимные функции используют (совместно использовать) одни и те же переменные ключа и значения из внешней области. Когда значение for закончено, значения, которые они используют, являются значением key22, а не значениями, которые они имели при определении функций.

for (var key in dataList) // definition of key 
{ 
    var value = dataList[key]; // definition of value 

    jobList.push(
     function (next) 
     { 
      console.log(key + ' : ' + value); // uses key and value from the outer scope 
     } 
    ); 
} 

(jobList[0])(); // key and value are key2 value2 after for, so they are printed 
(jobList[1])(); // same 

Решение создать замыкание в котором ключ и значение являются локальными:

for (var key in dataList) // definition of key 
{ 
    var value = dataList[key]; // definition of value 

    jobList.push(
     function(k,v){ // k,v local copies of key and value 
     return function (next) 
      { 
      console.log(k + ' : ' + v); // uses local copies, created one for each iteration 
      } 
     }(key,value); // immediately execute the outer anonymous function, it just creates a local scope 
    ); 
} 
2

Как заявил Теему, его потому, что к тому времени, что цикл закончен, значение уже изменилось

Что вам нужно сделать, это следующее:

var dataList = { key1: 'value1', key2: 'value2' }; 

var jobList = new Array(); 

for (var key in dataList) 
{ 
    var value = dataList[key]; 

    jobList.push(
     (function(savedKey, savedValue) { 
      return function (next) { 
       console.log(savedKey + ' : ' + savedValue); 
      } 
     })(key, value) 
    ); 
} 

(jobList[0])(); 
(jobList[1])(); 

Хотя savedKey и savedValue можно назвать key и value, и он будет ссылаться на новый, что может иметь смысл читать его

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