Почему перезагрузка возвращает пустое состояние половину времени?

#javascript #vue.js #vuex #nuxt.js

#javascript #vue.js #vuex #nuxt.js

Вопрос:

Я создаю веб-магазин для хобби-проекта в Nuxt 2.5. В хранилище Vuex у меня есть модуль с состоянием «currentCart». Здесь я храню объект с идентификатором и массив продуктов. Я получаю корзину из серверной части с идентификатором, который хранится в файле cookie (с помощью js-cookie).

Я использую nuxtServerInit для получения корзины из серверной части. Затем я сохраняю его в состоянии. Затем в компоненте я пытаюсь получить состояние и отобразить количество товаров в корзине, если значение корзины равно null, я показываю «0». Это дает странные результаты. В половине случаев он правильно сообщает, сколько в нем товаров, но инструменты разработки Vuex сообщают мне, что корзина пуста. В другую половину времени отображается «0».

Сначала у меня было промежуточное программное обеспечение, которое запускало действие в магазине, которое устанавливало корзину. Это вообще не работало последовательно. Затем я попытался настроить хранилище с помощью nuxtServerInit, что на самом деле сработало правильно. По-видимому, я что-то изменил, потому что сегодня это приводит к описанной проблеме. Я не могу выяснить, почему это создает эту проблему.

nuxtServerInit:

 nuxtServerInit ({ commit }, { req }) {
  let cartCookie;

  // Check if there's a cookie available
  if(req.headers.cookie) {

    cartCookie = req.headers.cookie
    .split(";")
    .find(c => c.trim().startsWith("Cart="));

    // Check if there's a cookie for the cart
    if(cartCookie)
      cartCookie = cartCookie.split("=");
    else
      cartCookie = null;
  }
  // Check if the cart cookie is set
  if(cartCookie) {

    // Check if the cart cookie isn't empty
    if(cartCookie[1] != 'undefined') {
      let cartId = cartCookie[1];

      // Get the cart from the backend
      this.$axios.get(`${api}/${cartId}`)
      .then((response) => {
        let cart = response.data;
        // Set the cart in the state
        commit("cart/setCart", cart);
      });
    }
  }
  else {
    // Clear the cart in the state
    commit("cart/clearCart");
  }
},
  

Мутация:

 setCart(state, cart) {
  state.currentCart = cart;
}
  

Средство получения:

 currentCart(state) {
  return state.currentCart;
}
  

В cart.vue:

 if(this.$store.getters['cart/currentCart'])
  return this.$store.getters['cart/currentCart'].products.length;
else
  return 0;
  

Объект состояния:

 const state = () => ({
  currentCart: null,
});
  

Я ставлю консоль.регистрирует везде, чтобы проверить, где что-то пошло не так. nuxtServerInit работает, коммит «cart / setCart» запускается и содержит нужное содержимое. В получателе большую часть времени я получаю null. Если я быстро перезагружаю страницу после другой перезагрузки, я получаю правильную корзину в получателе, и компонент получает правильное количество. Инструмент разработки Vue сообщает, что состояние currentCart равно null, даже если компонент отображает данные, которые я ожидаю.

Я изменил объект состояния на «currentCart: {}», и теперь он работает большую часть времени, но каждые 3/4 перезагрузки он возвращает пустой объект. Таким образом, очевидно, что средство получения срабатывает до того, как состояние установлено, в то время как состояние устанавливается nuxtServerInit . Это верно? Если да, то почему это так и как мне это изменить?

Чего я не понимаю? Я в полном замешательстве.

Ответ №1:

Итак, вы помните тот момент, когда вы ввели проблему для запроса в Stackoverflow, и после отправки у вас появилось несколько новых идей, которые можно опробовать? Это был один из них.

Я отредактировал вопрос, чтобы сказать, что когда я менял объект состояния на пустой объект, он иногда возвращал пустой объект. Затем меня осенило, средство получения иногда запускается перед nuxtServerInit . В документации говорится:

Примечание: Асинхронные действия nuxtServerInit должны возвращать обещание или использовать async / await, чтобы позволить серверу nuxt их дождаться.

Я изменил nuxtServerInit на это:

 async nuxtServerInit ({ commit }, { req }) {
  ...
  await this.$axios.get(`${api}/${cartId}`)
  .then((response) => {
    ...
  }
  await commit("cart/clearCart");
  

Итак, теперь Nuxt может дождаться результатов. Инструменты разработки по-прежнему показывают пустое состояние, но я думаю, что это ошибка, поскольку я могу прекрасно использовать состояние хранилища в остальной части приложения.

Ответ №2:

Заставьте сервер ждать результатов

Приведенный выше ответ сводится к утверждению.

У меня была такая же проблема, как у @Maurits, но с немного другими параметрами. Я использую не nuxtServerInit() , а хук выборки от Nuxt. В любом случае, идея по сути такова: вам нужно заставить сервер ждать завершения сбора данных.

Вот код для моего контекста; Я думаю, это полезно для тех, кто использует перехват выборки Nuxt. Для развлечения я добавил computed и mounted , чтобы проиллюстрировать, что хук выборки не включается methods .

СБОЙ:

(Я получил пустые страницы при обновлении браузера)

 computed: {
    /* some stuff */
},

async fetch() {
    this.myDataGrab()
    .then( () => {
        console.log("Got the data!")
    })
},

mounted() {
    /* some stuff */
}
  

РАБОТАЕТ:
Я забыл добавить await перед вызовом func! Теперь сервер будет ждать этого, прежде чем завершить и отправить страницу.

 async fetch() {
    await this.myDataGrab()
    .then( () => {
        console.log("Got the messages!")
    })
},