Переменная Coffeescript, возвращенная из обещания, объявленного в неверной области видимости - PullRequest
0 голосов
/ 13 июня 2018

У меня есть вопрос о предполагаемом поведении Coffeescript.Это ошибка?

Сопоставление элементов списка с помощью цикла for и повторное их получение - не проблема.

idList = [0, 1, 999]
results =
  for id in idList
    id
console.log results # prints [ 0, 1, 999 ]

Теперь давайте снова выведем их, завернув в обещание,Это ломается.

Лучше всего объяснить код.

С циклом for всегда печатается 999

idList = [0, 1, 999]
operations =
  for id in idList
    new Promise (resolve, reject) -> resolve()
    .then -> id

Promise.all operations
.then (results) ->
  console.log results # prints [ 999, 999, 999 ]

Можно подумать, id из строки цикла for (строка 3) объявляется внутри этой области.

При изменении строки 3 на использование карты она ведет себя так, как ожидается

idList = [0, 1, 999]
operations =
  idList.map (id) ->
    new Promise (resolve, reject) -> resolve()
    .then -> id

Promise.all operations
.then (results) ->
  console.log results # prints [ 0, 1, 999 ]

КогдаВозвращая переменную из обещания внутри цикла for и проверяя скомпилированный код Javascript, мы видим, что компилятор Coffee объявил переменную во внешней области видимости, и поэтому возвращаемое значение становится последним значением переменной,всегда.

var id, idList, operations;  # id is declared here
idList = [0, 1, 999];
operations = (function() {
   var i, len, results1;
   results1 = [];
  for (i = 0, len = idList.length; i < len; i++) {
    id = idList[i];
    results1.push(new Promise(function(resolve, reject) {
      return resolve();
    }).then(function() {
      return id;
      .......

Это действительно преднамеренно, это ошибка, или это предупреждение, о котором нужно знать?

CoffeeScript версия 2.1.1 версия узла v9.7.1

1 Ответ

0 голосов
/ 13 июня 2018

Ваше третье предположение верно - это предостережение, о котором нужно знать.

Это ожидаемое поведение, которое является распространенным источником ошибок как в Javascript, так и в Coffeescript.

переменная назначается в верхней области видимости внутри цикла.Если вы определяете функцию или обещание в цикле, они все будут ссылаться на одну и ту же переменную.Если функция / обещание выполняется после того, как цикл переместился, тогда переменная не будет содержать то, что вы ожидаете.Чтобы обойти это, используйте оператор do в Coffeescript, который компилируется в немедленно выполняемую анонимную функцию в Javascript.

Использование оператора do в вашем примере Promise:

idList = [0, 1, 999]
operations =
  for id in idList
    do (id) ->   
      new Promise (resolve, reject) -> resolve()
      .then -> id

Ознакомьтесь с официальными документами в конце раздела циклы и понимания :

При использовании цикла JavaScript для генерации функций обычно вставляютзакрывающая оболочка, чтобы гарантировать, что переменные цикла закрыты, и все сгенерированные функции не просто разделяют конечные значения.CoffeeScript предоставляет ключевое слово do, которое немедленно вызывает переданную функцию и передает любые аргументы.

...