#angular #rxjs #ngxs
#угловой #rxjs #ngxs
Вопрос:
Я создаю игровой модуль, который отвечает за загрузку игрока buildings
, а затем модифицирует выбранные объекты в расширенный класс зданий, содержащий дополнительное поле — Оставшееся время, информирующее, сколько секунд осталось до завершения обновления lvl зданий (это поле обновляется каждую секунду).
buildings
-> buildingsWithDiff
-> buildingsWithTimer
- Загрузка
buildings
- Сопоставьте
buildings
buildingsWithDiff
, чтобы узнать разницу между датой начала таймера и датой окончания обновления - Сопоставление
buildingsWithDiff
, вbuildingsWithTimer
которое вычитается количество тиков из результирующей разницы
class Building {
name: string;
lvl: number;
endDate: Date; // date of upgrading of the building
}
class BuildingWithDiff extends Building {
diffTime: number; // difference of seconds between the currentDate and the endDate;
}
class BuildingWithTimer extends BuildingWithDiff {
remainingTime: number; // seconds left to complete upgrading a building
}
/* ------------- */
const getBuildings$ = (store: Store): Observable<Building[]> => {
const buildings$: Observable<Building[]> = store.select(
(appState: AppState) => appState.buildings
); // source
return buildings$;
};
const getBuildingsWithTimers$ = (
store: Store
): Observable<BuildingWithTimer[]> => {
const buildings$: Observable<Building[]> = getBuildings$(store);
const buildingsWithDiff$: Observable<BuildingWithDiff[]> = buildings$.pipe(
map((buildings) =>
buildings.map((building) => {
const currentDate: Date = new Date();
const diffTime: number =
Math.ceil(
building.endDate.getTime() - currentDate.getTime()
) / 1000;
return {
...building,
diffTime,
};
})
)
);
const buildingsWithTimer$: Observable<BuildingWithTimer[]> = buildingsWithDiff$.pipe(
switchMap((buildingsWithDiff) =>
timer(0, 1000).pipe(
map((tick: number) =>
buildingsWithDiff.map((buildingWithDiff) => {
const remainingTime: number = buildingWithDiff.diffTime - tick;
return {
...buildingWithDiff,
remainingTime,
};
})
)
),
// share()? - it doesn't work :(
)
);
return buildingsWithTimer$;
};
Многоадресная рассылка вложенных таймеров — как это сделать?
Подписка на селектор выше генерирует ошибки, потому что есть несколько наблюдателей, и не все из них выполняются одновременно. Добавление share
оператора не работает. В чем может быть проблема?
Есть два места, где это подписано:
trigger
— функция, которая вызывается в ngxsOnInit (ожидаетremainingTime <= 0
отправки соответствующего действия)building component
— угловой компонент, который отображает оставшееся время
Приложение работает нормально, когда я включаю его на подстранице, где существует этот компонент — оба наблюдателя отображают одинаковое значение тика в таймере.
Проблема заключается в том, что когда я выхожу из подстраницы, на которой находился компонент, потому trigger
что он работает все время, и тики все еще подсчитываются, но компонент завершает подписку, и когда я хочу вернуться на подстраницу, тики отсчитываются от нуля.
В конечном счете, есть два разных тика.
Комментарии:
1. Какую фактическую ошибку вы получаете?
2. Когда вы их используете? Может быть, хранилище еще не загружено.
3. Ha. Я не привык видеть функции, названные с завершением .
$
Бросил меня в цикл. Выдает ли поток, возвращаемый с помощьюgetBuildings$()
, более одного раза? Я предполагаю, что нет, это просто запрос к вашим данным?4. @MrkSef — в этом простом примере это обычный запрос, но в моем приложении это не всегда так. В других, более продвинутых модулях данные изменяются во время работы приложения
5. Я думаю, было бы очень полезно создать StackBlitz, где вы иллюстрируете свою проблему и ожидаемые результаты.