Массивы JavaScript не совпадают

Сюда я прилагаю скриншоты результатов моего консольного журнала. Оба они - Объекты. Но они не такие. В чем может быть проблема? Один показывает

(5) [{..},{..},{..},{..},{..}]

Другой просто показывает [].

let tmp_array = [];
    this.database.ref('/users/').once('value', (snapshot) => {
      snapshot.forEach( (childSnapshot) => {
      var key = (childSnapshot.val() && childSnapshot.key) || 'Anonymous'; 
      var name = (childSnapshot.val() && childSnapshot.val().name) || 'Anonymous';    
      var email = (childSnapshot.val() && childSnapshot.val().email) || 'Anonymous';
      tmp_array.push({ key: key, email: email, name: name });
    });
    this.setState({ data: tmp_array });
    this.getImageList(tmp_array);
    console.info(tmp_array);
 });


let tmp_array2 = [];
    lodash.forEach(tmp_array, (value, key) => {
      this.storage.ref().child(value.key + '.jpg').getDownloadURL().then(function (url) {
        tmp_array2.push({ id: value.key, image: url });
    });
});
this.setState({ image: tmp_array2 });
console.info(tmp_array2);

Массивы JavaScript не совпадают

Массивы разные. В чем проблема? Этот вопрос не имеет смысла.

Charlie Fish 28.12.2018 19:47

Пользователи Stack Overflow не смогут ответить вам, если вы не включить соответствующую часть вашего кода. Пожалуйста, отредактируйте свой вопрос как таковой

Nino Filiu 28.12.2018 19:47

Я добавил свой код, пожалуйста, проверьте его

GunarathneMDD 28.12.2018 19:56
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
6
3
68
2

Ответы 2

[] - пустой массив. Другой [{..}, {..}, {..}, {..}, {..}] - это массив, содержащий 5 объектов. Поскольку вы не указали, какой временный массив представляет какой регистрируемый массив, я не могу помочь вам определить, почему один массив пуст.

Добро пожаловать в программирование с помощью веб-API. У вас типичная проблема с асинхронностью. Я объясню, что происходит в вашем коде, затем дам вам первые шаги к решению, укажу на некоторые дополнительные соображения и, наконец, предоставлю ссылки с дополнительной информацией, чтобы вы могли прочитать эту невероятно распространенную (но изначально одинаково запутанную) тему.

Проблема: URL-адреса загрузки загружаются асинхронно

Ваш код вызывает getDownloadURL, что происходит асинхронно. Это означает, что ваш другой код продолжается, пока загружается URL. Затем, когда URL-адрес загружен, ваш обратный вызов вызывается с URL-адресом. Это означает, что любой код, которому нужен URL-адрес, должен находиться внутри обратного вызова.

Это легче всего увидеть, если вы просто наберете код и добавите несколько операторов журнала:

console.info("Before starting getDownloadURL");
this.storage.ref().child(value.key + '.jpg').getDownloadURL().then(function (url) {
    console.info("Got download URL");
});
console.info("After starting getDownloadURL");

Когда вы запускаете этот код, он печатает:

Before starting getDownloadURL

After starting getDownloadURL

Got download URL

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

Решение: поместите весь код, которому нужен URL-адрес загрузки, в обратный вызов

Чтобы решить эту проблему, весь код, которому требуется URL-адрес загрузки из базы данных, должен быть внутри обратным вызовом (или вызываться оттуда). Итак, первым шагом будет:

let tmp_array2 = [];
lodash.forEach(tmp_array, (value, key) => {
  this.storage.ref().child(value.key + '.jpg').getDownloadURL().then(function (url) {
    tmp_array2.push({ id: value.key, image: url });
    this.setState({ image: tmp_array2 });
    console.info(tmp_array2);
  });
});

Когда вы запустите это, вы увидите, что он регистрирует массив так же часто, как и дочерние узлы / изображения. Каждый раз, когда он получает URL-адрес загрузки (помните: это происходит асинхронно), он добавляет его в массив, а затем сообщает React, что состояние изменилось (чтобы он мог обновить пользовательский интерфейс).

Некоторые дополнительные соображения и проблемы

В моем последнем фрагменте кода есть еще подводные камни:

  1. Повторный вызов setState() может привести к частичному обновлению пользовательского интерфейса или мерцанию. В этом случае подумайте о том, чтобы проверить, получили ли вы все URL-адреса для загрузки, прежде чем вызывать setState с чем-то вроде: if (tmp_array2.length === tmp_array.length) this.setState({ image: tmp_array2 });.
  2. Вызовы URL-адреса загрузки происходят асинхронно и могут (я думаю, это зависит от внутренней реализации этого API) завершаться в другом порядке, чем вы их вызываете. Другими словами: URL-адрес загрузки для второго изображения может быть возвращен перед URL-адресом загрузки для первого изображения. Если это вызывает беспокойство для вашего приложения, обязательно либо реплицируйте другую информацию для изображения в tmp_array2 (я думаю, вы уже это делаете), либо рассмотрите возможность сохранения URL-адресов загрузки таким образом, чтобы вы могли связать их обратно с элементами. в tmp_array.

Больше информации

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

Другие вопросы по теме