Vladimir_Denisov
@Vladimir_Denisov
JS (Angular2 & Node) / Python (Django)

Как дождаться окончания запроса, инициированного в другом компоненте?

Вопрос к знатокам Angular2.
В данный момент делаю проект интернациональным (ngx-translate), но возникла проблемка.

* [картинка 1] -> AppComponent
При инициализации компонента AppComponent выполняется функция translateSetup(), которая записывает в переменную languageCode код языка (по умолчанию, либо английский) и после сохраняет это значение в localStorage.
В конструкторе я подписываюсь на пользователя, и, если он пришёл, то в переменную languageCode устанавливаю выбранный им язык и перезаписываю значение в localStorage.
59d11c46154f5804352677.png

* [картинка 2] -> FooterComponent
При инициализации компонента FooterComponent (который является дочерним для AppComponent) я беру значение languageCode из localStorage и далее использую его (например, просто печатаю в консоли).
Однако, я ожидаю, что если в AppComponent попадёт таки ин-фа о пользователе и данные в localStorage перезапишутся, то FooterComponent дождётся окончания этого процесса.
59d11c531f414562033105.png

* [картинка 3] -> ConsoleLog
По выводу в консоли получается, что сначала инициализировался AppComponent, потом инициализировался FooterComponent, а потом пришла ин-фа о пользователе. И да, localStorage перезаписался, но FooterComponent уже не получит этих изменений, так как он инициализировался раньше.
59d11c60914d9678136180.png

Как сделать так, чтобы в FooterComponent начинал работать только после того, как выполнется код в конструкторе компонента AppComponent (то место, где выполнятся подписка) ?
Или может вы предложете более подходящий способ.

P.S.: заранее спасибо !
  • Вопрос задан
  • 838 просмотров
Пригласить эксперта
Ответы на вопрос 3
@denismaster
Несколько вариантов навскидку.
1) Если FooterComponent расположен рядом с AppComponent, использовать EventEmitter=)
2) Если же футер внутри AppComponent, то просто делаете Input-свойство внутри Footer, потом просто делаете биндинг.
3) Создать Observable на основе события "storage", которое возникает при изменении localStorage. Подробнее тут и тут. Но следует учесть, что событие возникает на других вкладках.
Ответ написан
Комментировать
uaKorona
@uaKorona
Front-End разработчик
Хорошим решением может быть использование Observable - а точнее BehaviorSubject.
Он в отличие от Observable всегда возвращает последнее сохраненное значение.

Вы инициализируете приложение, берете код из локалСторедж и помещаете его в BehaviorSubject.
Все остальные компоненты подписываются на него и получают последнее значение.
Если в какой-то момент, значение изменится (незнаю, пользователь выбрал другой язык) - вы опять помещаете его в BehaviorSubject и все подписанные на него компоненты (слушатели) будут уведомлены об изменении

// Behavior Subject

// инициализируем где-то в сервисе и помещаем первое значение 
bSubject = new BehaviorSubject("a"); 

// создаем метод который будет возвращать наш инстанс bSubject 
getSubject = () => return this.bSubject

// В компененте инжектим сервис, вызываем метод getSubject и подписываемся
bSubject.subscribe((value) => {
  console.log("Subscription got", value); 
// Тут выполняем действия при смене языка 
});

// Позже в другом месте пользователь меняет язык и мы сохраняем его опять в поток 
bSubject.next("c"); // Subscription got c
Ответ написан
Комментировать
mazhekin
@mazhekin
Frontend, Backend Web Developer
Правильным решением будет перенести код получения языка в Resolver корневого роута, который будет парентом для всех остальных роутов проекта. https://angular.io/api/router/Resolve
Тогда в любом случае сторадж(или апи к серверу) прочитается прежде чем любые иниты любого компонента. Ибо нет смысла показывать любую страницу если мы не знаем еще языка.

А там можно и записать в BehaviorSubject. Который можно будет читать в любом компоненте не боясь что он пустой
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы