Http-вызовы выполняются дважды в угловом универсальном

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

if (isPlatformBrowser(this.platformId)) {
 return this.http.get(baseApi + '/blog/slug/' + blogId);
} else {
  const store = this.state.get(MY_DATA, null);
  if (store) {
    return store;
  }
  const myData = this.http.get(baseApi + '/blog/slug/' + blogId);
  this.state.set(MY_DATA, myData);
  return myData;
}

Скриншот сетевых вызовов введите здесь описание изображения

Я что-то упустил или есть что-то, что я должен включить, чтобы избежать вызовов браузера? Заранее спасибо.


person gautam siva    schedule 04.03.2020    source источник
comment
Вы можете кэшировать данные только с передачей состояния. Похоже, вы пытаетесь кэшировать наблюдаемое. И ваш первый, если он неверен, это означает, что вы всегда будете делать HTTP-вызов на стороне клиента.   -  person David    schedule 04.03.2020
comment
Настоящая проблема заключается в том, что angular ssr дважды вызывает API при начальной загрузке из браузера и сервера. Здесь я должен ограничить вызовы браузера, поэтому из моего недавнего исследования я узнал, что, используя этот способ, мы можем ограничить вызовы браузера. Но ничего не работает и по-прежнему вызов выполняется дважды. Есть ли какое-либо решение для этого, поскольку проблема все еще открыта в Github?   -  person gautam siva    schedule 05.03.2020
comment
Предоставьте данные о совершенных звонках в сети. Воспользуйтесь инструментами разработчика браузера, перейдите на вкладку «Сети», сделайте скриншот звонков. Добавьте скриншот к вопросу.   -  person 0leg    schedule 05.03.2020
comment
В моей сети я вижу дополнительный вызов API, который выполняется. Итак, здесь один вызов API выполняется сервером, а другой - клиентом, а также скриншот прикрепленных сетевых вызовов.   -  person gautam siva    schedule 06.03.2020


Ответы (3)


если ваше условие проверено, оно выполняет запрос

if (isPlatformBrowser(this.platformId)) {
  return this.http.get(baseApi + '/blog/slug/' + blogId);
 } 

в противном случае он входит в else, за исключением того, что

const myData = this.http.get(baseApi + '/blog/slug/' + blogId);
  this.state.set(MY_DATA, myData);
  return myData;

всегда выполняется независимо от выполненного теста.

person christ_dev    schedule 04.03.2020
comment
Но все же вызовы выполняются дважды, когда страница попадает в браузер, нужно ли мне использовать какой-либо файл-перехватчик для глобального ограничения? - person gautam siva; 05.03.2020

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

Чтобы избежать повторных вызовов, вы можете использовать что-то вроде приведенного ниже кода, который также предотвратит повторный вызов на стороне сервера.

//Check if cached version exists
const data = this.state.get(MY_DATA, null);
if (data) 
{
    return of(data); //data exists
}

//Data has not been cached yet. Make the call and store result

return this.http.get(baseApi + '/blog/slug/' + blogId)
.pipe(tap(res=> {this.state.set(MY_DATA, res);} );

Вы также можете использовать более TransferStateHttpCacheModule, который предоставляет общий перехватчик, который делает это для всех ваших запросов

person David    schedule 05.03.2020
comment
Я уже пробовал, что проблема с TransferStateHttpCacheModule все еще сохраняется. У меня мерцающий глюк. - person gautam siva; 05.03.2020
comment
TransferStateHttpCacheModule не работает - person Offir; 11.03.2021

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

npm i preboot

добавьте код ниже при импорте app.module.ts

PrebootModule.withConfig({ appRoot: 'app-root' })

Также добавьте приведенный ниже код к своим провайдерам в app.module.ts, если это необходимо,

{
provide: APP_INITIALIZER,
  useFactory: function(document: HTMLDocument, platformId: Object): Function {
    return () => {
      if (isPlatformBrowser(platformId)) {
        const dom = ɵgetDOM();
        const styles: any[] = Array.prototype.slice.apply(dom.querySelectorAll(document, `style[ng-transition]`));
        styles.forEach(el => {
          // Remove ng-transition attribute to prevent Angular appInitializerFactory
          // to remove server styles before preboot complete
          el.removeAttribute('ng-transition');
        });
        document.addEventListener('PrebootComplete', () => {
          // After preboot complete, remove the server scripts
          setTimeout(() => styles.forEach(el => dom.remove(el)));
        });
      }
    };
  },
  deps: [DOCUMENT, PLATFORM_ID],
  multi: true  
}

И после их добавления для меня проблема мерцания была решена.

Обратитесь к официальной ссылке angular ssr для большей ясности: https://angular.io/guide/universal

person gautam siva    schedule 07.03.2020
comment
@gautam Мне не удалось найти никакой информации о том, что предварительная загрузка предотвращает двойные HTTP-вызовы. Это действительно так? - person Shyamal Parikh; 17.08.2020
comment
извините за поздний ответ, да, это так. В основном это помогает вам избежать мерцания - person gautam siva; 11.10.2020
comment
Нет, по-прежнему повторяются вызовы - person Casper Nybroe; 27.01.2021