Angular DI - useFactory - Provider: есть ли способ вызвать функцию Provider Factory во второй раз, когда обновляется локальное состояние?
Сценарий выглядит следующим образом:
1. В приложении есть корневой модуль, а конструктор разрешает Promise и возвращает константу.
@NgModule({
....,
providers : [
...
{
provide: SAMPLE_INJECTOR_TOKEN,
useFactory: sampleFactoryFn(SAMPLE_GLOBAL_CONSTANT.DATA)
}
]
})
export class AppModule {
constructor() {
// To be clear: This code runs on window.onLoad(). window argument is actually window object
setupPromiseAPI(window).then(data => {
SAMPLE_GLOBAL_CONSTANT.DATA = data; // Once promise resolves this gets expected value. [ Step 3 ]
}).catch({
...
})
}
2. Поскольку это значение является объектом, а также, поскольку оно будет доступно во время выполнения, я создал токен инъекции с использованием "useFactory" и зарегистрировался на уровне модуля.
// Injector Token
export SAMPLE_INJECTOR_TOKEN = new InjectionToken<CustomDataType>('SampleInjectorToken');
// Factory Function
export function sampleFactoryFn(data: CustomDataType) {
return (/* No deps to be passed */): CustomDataType => data; // simply return what ever it received.
}
3. Я создал глобальную константу, инициализированную нулем и переданную в качестве аргумента фабричной функции, с помощью которой angular создает токен инжектора и присваивает значение null (начальное состояние) при начальной загрузке.
export const SAMPLE_GLOBAL_CONSTANT = {
DATA: null // Initial State
}
4. Когда обещание получено из шага 1, я извлекаю возвращенное значение константы из Promise и присоединяюсь к этой объявленной глобальной константе, как ее константе, которая, очевидно, обновляется и доступна через приложение.
Кроме того, угловая документация гласит, что поставщик useFactory лениво создает свое значение, которое, насколько я понимаю, будет создано при его внедрении. Если это так, к тому времени, когда код вводит мой токен инъекции, глобальная константа обновляется. Тем не менее токен инжектора имеет нулевое значение.
Q1. Есть ли способ вызвать функцию фабрики провайдера с обновленным локальным состоянием, чтобы мой токен инжектора получил значение?
Q2. Так как я использую глобальную константу, она делает код работающим, но не слабо связанным, что также затрудняет модульное тестирование. Есть ли альтернативы потреблять полученную константу и использовать ее в коде, чтобы она была слабо связана?
1 ответ
Один из способов, который я решил, это использование Replay Subject из RxJS. Прежде всего, это сервис postMessage, завернутый в обещание. Итак, после того, как сообщение было отправлено (из другого приложения) и обещание было разрешено (при использовании приложения), должен быть способ хранения этих данных для их использования в приложении.
Использование субъекта воспроизведения со значением буфера 1, что означает воспроизведение последнего значения в подписке, приводит к получению последнего перехваченного значения после разрешения вышеуказанного сценария.
Затем передайте полученные данные подписке в Angular Service, что сделает их доступными через приложение.
Теперь это делает необходимые данные в угловой службе, а не в глобальной константе, что облегчает модульное тестирование.
NB: Factory Provider не разрешает эту ситуацию, потому что angular пытается разрешить до того, как произойдет запуск, который по умолчанию равен инициализированному значению (в моем случае это было нулевое значение). Так что это не сработает.
Почему не Async Subject?
Поскольку Async Subject получает сигнал только после завершения, а бизнес-пример, который я решаю, должен выполнить промежуточную работу, прежде чем объявить сигнал завершения. Это не решило цель.