Как использовать несколько отправлений в nuxt fetch?

#promise #fetch #nuxt.js

Вопрос:

Я создаю сайт в nuxt и получаю данные из api worpdress. У меня есть несколько магазинов: home.js, solutions.js, tipo.js, portfolio.js и options.js.

В fetch я проверяю, пуст ли массив хранилища, чем вызываю диспетчеризацию и заполняю массивы.

 export default {
  async fetch({ store }) {
    try {
      if (store.getters['home/home'].length === 0) {
        await store.dispatch('home/fetchHome');
      }
      if (store.getters["solutions/getSolutions"].length === 0) {
        await store.dispatch('solutions/fetchSolutions');
      }
      if (store.getters["tipo/getTipo"].length === 0) {
        await store.dispatch('tipo/fetchTipo');
      }
      if (store.getters["portfolio/getPortfolio"].length === 0) {
        await store.dispatch('portfolio/fetchPortfolio');
      }
      if(store.getters["options/getOptions"].length === 0){
        await store.dispatch('options/fetchOptions');
      }
    } catch (e) {
      console.log(e, 'e no data')
    }
  },
  components: { HomeContacts, PortofolioSlider, Clients, ChiSiamo, Solutions, HomeIntro }
}

 

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

Как я могу вызывать все отправки в fethc без асинхронности, но параллельно?

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

Просто в nuxt очень мало информации с точки зрения идеологии, как работать, что лучше использовать и когда. В следующем, это лучше.

Этот метод не работает.

 fetch({ store }) {
  const promise1 = new Promise((resolve, reject) => {
    if (store.getters['home/home'].length === 0) {
      resolve(store.dispatch('home/fetchHome'));
    }
  });
  const promise2 = new Promise((resolve, reject) => {
    if (store.getters["solutions/getSolutions"].length === 0) {
      resolve(store.dispatch('solutions/fetchSolutions'));
    }
  });
  const promise3 = new Promise((resolve, reject) => {
    if (store.getters["tipo/getTipo"].length === 0) {
      resolve(store.dispatch('tipo/fetchTipo'));
    }
  });
  const promise4 = new Promise((resolve, reject) => {
    if (store.getters["portfolio/getPortfolio"].length === 0) {
      resolve(store.dispatch('portfolio/fetchPortfolio'));
    }
  });
  const promise5 = new Promise((resolve, reject) => {
    if (store.getters["options/getOptions"].length === 0) {
      resolve(store.dispatch('options/fetchOptions'));
    }
  });
  Promise.all([promise1, promise2, promise3, promise4, promise5])
    .then((data) => console.log(data))
    .catch((error) => console.log(error));

 

Комментарии:

1. Каков следующий подход к этому вопросу?

2. страница загружается в течение длительного времени = api wordpress, решение состоит в том, чтобы создать свой собственный api wp с уменьшенными функциями (стандартный api bog загрузит весь wp, но просто не будет выводить html) или совершать меньше вызовов или по мере необходимости, кроме того, вы можете использовать цикл для сохранения нескольких строк и не делать его асинхронным

3. @LawrenceCherone так что на самом деле ничего не связано с интерфейсом. В чем различия между Nuxt и Next для извлечения данных, только с точки зрения интерфейса?

4. асинхронность по-прежнему играет важную роль

5. @LawrenceCherone async пока такой же в Next и Nuxt.

Ответ №1:

Предполагая, что:

  • store.dispatch() возвращает Обещание,
  • первая попытка в вопросе в целом верна,
  • цель состоит в том, чтобы параллельно выполнять соответствующие отправки,

затем:

  • исключить await из store.dispatch() последовательности,
  • накапливайте обещания, возвращаемые store.dispatch() в массиве,
  • не используйте new Promise() обертку,
  • await обещание вернулось Promise.all(promises) .
     export default {
        async fetch({ store }) {
            try {
                let promises = [];
                if (store.getters['home/home'].length === 0) {
                    promises.push(store.dispatch('home/fetchHome'));
                }
                if (store.getters['solutions/getSolutions'].length === 0) {
                    promises.push(store.dispatch('solutions/fetchSolutions'));
                }
                if (store.getters['tipo/getTipo'].length === 0) {
                    promises.push(store.dispatch('tipo/fetchTipo'));
                }
                if (store.getters['portfolio/getPortfolio'].length === 0) {
                    promises.push(store.dispatch('portfolio/fetchPortfolio'));
                }
                if(store.getters['options/getOptions'].length === 0) {
                    promises.push(store.dispatch('options/fetchOptions'));
                }
                let data = await Promise.all(promises);
                console.log(data);
            } catch (e) {
                console.log(e);
            }
        },
        components: { HomeContacts, PortofolioSlider, Clients, ChiSiamo, Solutions, HomeIntro }
    }
     

Для удобства это может быть оформлено следующим образом:

 export default {
    async fetch({ store }) {
        try {
            let paths = [
                { get: 'home/home',              fetch: 'home/fetchHome' },
                { get: 'solutions/getSolutions', fetch: 'solutions/fetchSolutions' },
                { get: 'tipo/getTipo',           fetch: 'tipo/fetchTipo' },
                { get: 'portfolio/getPortfolio', fetch: 'portfolio/fetchPortfolio' },
                { get: 'options/getOptions',     fetch: 'options/fetchOptions' }
            ];
            let promises = paths.filter(p => store.getters[p.get].length === 0).map(p => store.dispatch(p.fetch));
            let data = await Promise.all(promises);
            console.log(data);
        } catch (e) {
            console.log(e);
        }
    },
    components: { HomeContacts, PortofolioSlider, Clients, ChiSiamo, Solutions, HomeIntro }
}
 

Возможно , имеет смысл определить paths массив в другом месте кода и передать его в упрощенный fetch() , придав ему профиль :

     fetch({ store, paths })
 

Если это все еще не работает, значит, есть что-то, о чем вы нам не говорите.

Комментарии:

1. Большое спасибо. Я решил этот вопрос таким же образом. i.imgur.com/MfS3O3M.png Пожалуйста, не могли бы вы помочь мне с такой же выборкой, но с фиксациями. i.imgur.com/ciBWy0A.png Большое спасибо.

2. @serii, я, возможно, смогу помочь с фиксациями, но вам придется задать формальный вопрос, отправив другой вопрос.

Ответ №2:

Promise.all может быть полезно здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Или даже Promise.allSettled() , в зависимости от того, что вы пытаетесь сделать: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

Затем это вопрос отображения чего-либо, пока ваша страница выполняет выборку. Вы можете использовать a v-if="$fetchState.pending" на верхнем уровне вашей страницы, чтобы отобразить загрузчик, пока все это загружается.

Здесь нет ничего, связанного с идеологией, есть 2 крючка, которые выполняют извлечение данных, либо блокируя визуализацию страницы ( asyncData() ), либо позволяя вам визуализировать ее во время извлечения данных ( fetch() ).

Ничего не связано с фреймворком само по себе, вы вольны поступать так, как вам заблагорассудится.

Комментарии:

1. На мой взгляд, проблема в том, что я привык много ждать. Потому что первое ожидание должно быть выполнено, затем второе, третье. И как делать запросы на сервер параллельными, как мы говорим, залпом, параллельно и последовательно.

2. Если я добавлю такое обещание, это решит проблему? ` const promise1 = новое обещание((разрешить, отклонить) => { setTimeout (() = > > { разрешить( если (store.getters[‘home/home’].длина === 0) { store.dispatch(‘home/fetchHome’); } ); }, 2000); }); const promise2 = новое обещание((разрешить, отклонить) =>>> { setTimeout (() = > > > > { разрешить(‘Promise2 выполнен’); }, 1500); }); Обещание.все([обещание 1, обещание 2]) .затем((данные) =>>>>> console.log(данные[0], данные[1])). поймать((ошибка) = > > > > > > console.log(ошибка)); `

3. @serii 2 первые строки моего ответа связаны с вашим первоначальным вопросом о том, чтобы иметь несколько вызовов API одновременно. Вы не должны использовать setTimeout здесь, потому что это не что-то надежное, async/await здесь работает намного лучше.