Javascript JSON.stringify возвращает []

Я работаю с ReactJS, и мне нужно создать массив для вставки данных, сохранить их в localStorage и просмотреть позже. Сначала я создаю массив с помощью this.subscriptionsList = [];, а затем использую этот метод для извлечения данных.

  fetchNow = async (token, nextToken) => {
      fetch("somewebsite")
        .then(( unformattedData ) => {
          return unformattedData.json();
        })
        .then(( webData) => {
          for(let i = 0; i < webData.length; i++){
            this.subscriptionsList.push("someData");
          }
          if (webData.hasOwnProperty('token')){
            this.fetchNow(token, webData.token);
          }else{
            return;
          }
        })
      }

Функция не завершена, так как это не главная тема моего вопроса. Он отлично работает и передает правильные данные.

Я получаю данные с помощью этого метода:

this.fetchNow(response.accessToken, "")
      .then( () => {
        console.info(this.subscriptionsList);
        console.info(JSON.stringify(this.subscriptionsList));
        localStorage.setItem("subscriptionsList", JSON.stringify(this.subscriptionsList));
        //console.info(JSON.parse(localStorage.getItem("subscriptionsList")));
      })

Проблема возникает при попытке использовать JSON.stringify. Выполнение console.info(this.subscriptionsList) печатает объект массива со всеми данными внутри него, как и ожидалось. Однако, когда я иду делать console.info(JSON.stringify(this.subscriptionsList)), он возвращает []. Кроме того, при печати самого объекта свойство length: 125, но при выполнении console.info(this.subscriptionsList.length) оно возвращает 0, а при доступе с использованием this.subscriptionsList[0] возвращает undefined. Я читал спецификации, и похоже, что JSON.stringify должен работать с массивом javascript. Мне не хватает чего-то конкретного, или это просто недоступно с JSON.parse?

https://gyazo.com/72aafe248ef61649a38c06d03fb3d830
https://gyazo.com/c2690b4392774fe4a98254a4d15f3a32
https://gyazo.com/e0793b5ec05da4259e16100f275da414

Не могли бы вы скриншот структуры объекта

RIYAJ KHAN 09.06.2018 07:00

Не уверен, не могли бы вы попытаться сохранить this.subscriptionsList в локальной переменной и выполнить с ней операцию.

Kishan Mundha 09.06.2018 07:01

Я думал, что знаю, в чем проблема, пока вы не сказали, что логирование свойства length показывает другое значение, чем наблюдение свойства length, что практически невозможно. Вы в этом уверены?

Grant Gryczan 09.06.2018 07:01
Поведение ключевого слова "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) для оценки ваших знаний,...
1
3
262
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

fetchNow = (token, nextToken) => {
  return fetch("somewebsite")
    .then(( unformattedData ) => {
    return unformattedData.json();
  })
    .then(( webData) => {
    for(let i = 0; i < webData.length; i++){
      this.subscriptionsList.push("someData");
    }
    if (webData.hasOwnProperty('token')){
      return this.fetchNow(token, webData.token);
    }
  })
}

Функции async не делают асинхронные операции волшебным образом синхронными. Они (1) возвращают обещания и (2) разрешают ключевое слово await. Но поскольку вы не используете await, нет необходимости, чтобы fetchNow был async, а поскольку цепочка fetch уже является Promise, вы можете вернуть ее напрямую без async.

Если вы делать хотите использовать async и await, это сделает код более плоским и понятным:

fetchNow = async (token, nextToken) => {
  const response = await fetch("somewebsite");
  const webData = await response.json();
  for(let i = 0; i < webData.length; i++){
    this.subscriptionsList.push("someData");
  }
  if (webData.hasOwnProperty('token')){
    await this.fetchNow(token, webData.token);
  }
  // async function will automatically return a Promise that resolves when the end is reached
}

Согласно комментарию @Jimmy console.info(this.subscriptionsList) prints an array object with all the data inside of it as expected, это не проблема с цепочкой обещаний.

RIYAJ KHAN 09.06.2018 07:03

Это связано с нелогичной реализацией console.info - он регистрирует объект жить, а не объект, как это было было, когда он был зарегистрирован.

CertainPerformance 09.06.2018 07:04

См. Здесь: stackoverflow.com/questions/24175017/… (это не ограничивается Chrome, еще много вопросов по этой проблеме)

CertainPerformance 09.06.2018 07:08

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

Jimmy 09.06.2018 07:22

@Jimmy console.info не интуитивно возвращает объект жить, а не объект на момент регистрации. Если вы сделаете stringify объект заранее, он будет более точно представлять содержимое объекта в данный момент времени.

CertainPerformance 09.06.2018 07:24

Вот что происходит ... console.info(JSON.stringify(something)) делает то, что сериализует непосредственное значение и печатает сериализованную ссылку. (Другими словами, он создает клонированную копию и печатает клонированную копию, а не исходную ссылку, которую он не будет ждать поднятого / измененное значение). Что делает console.info(something), так это то, что он обращается к исходному значению и печатает фактический результат (измененный / поднятый), а не немедленный результат. Поскольку ваш метод является асинхронным, вы можете четко это заметить. Вы можете подождать, пока не будет выполнен вызов asyc, затем вы можете отправить фактическую переменную в localStorage. (Обратите внимание, что даже локальное хранилище хранится как сериализованные значения)

Изменить 1: -

let onComplete = (subscriptionsList) => {
    console.info(JSON.stringify(subscriptionsList));
    localStorage.setItem("subscriptionsList", JSON.stringify(subscriptionsList));
    //console.info(JSON.parse(localStorage.getItem("subscriptionsList")));
}

fetchNow = async (token, nextToken, onComplete) => {
  fetch("somewebsite")
    .then(( unformattedData ) => {
      return unformattedData.json();
    })
    .then(( webData) => {
      for(let i = 0; i < webData.length; i++){
        this.subscriptionsList.push("someData");
      }
      if (webData.hasOwnProperty('token')){
        this.fetchNow(token, webData.token);
      }else{
        onComplete(this.subscriptionsList);
        return;
      }
    })
}

this.fetchNow(response.accessToken, "", onComplete)
  .then( () => {
    console.info("direct call ", this.subscriptionsList);
})

Я действительно не понимаю, о чем вы говорите, поскольку я не слишком знаком с подъемом и т. д. В javascript. Насколько я понимаю, вы говорите, что каким-то образом массив становится пустым? Однако это не так. В конечном результате должны быть все данные. Я включил скриншоты в свой исходный пост для получения более подробной информации.

Jimmy 09.06.2018 07:20

@Jimmy попробуйте пример кода в edit1, но не тестировал его. Все, что вам нужно сделать, это дождаться завершения асинхронного вызова.

karthik 09.06.2018 07:41

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

Jimmy 09.06.2018 08:06

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