ПРИМЕЧАНИЕ: Кэширование JavaScript результаты обещания не применяется, потому что этот вопрос не касается API, который вызывает обратный вызов слушателя при изменении состояния (что означает, что API сохраняет функцию слушателя и может вызывать его несколько раз, когда его состояние обновляется).
У меня есть тип объекта состояния State
.
Теперь у меня есть API API.addEventListener()
, который принимает слушатель типа function(!State):undefined
и логическое repeating
. При вызове этот API сохранит обратный вызов слушателя и вызовет его с помощью объекта State
, если
- a
State
станет доступным (от несуществования к существованию) - новый
State
объект становится доступным (мутация), если repeating
истинно.
Первоначально, всякий раз, когда я вызываю doStuff()
для выполнения моего logi c, я буду вызывать API.addEventListener()
, чтобы получить Самый последний объект State
:
/**
* @return {!Promise{!State}}
*/
function getStatePromise() {
return new Promise(resolve => {
API.addEventListener(resolve, /* repeating */ false);
});
}
function doStuff() {
getStatePromise().then(state => {
// my logic
});
}
doStuff()
может вызываться несколько раз в разных точках моей программы.
Теперь я хотел бы кэшировать результат, полученный из API.getState()
в постоянном объекте в моем JS скрипте, и пусть код обновит кеш, когда станет доступен новый State
. Я не хочу менять doStuff()
, потому что это довольно сложно. Можно ли просто изменить getStatePromise()
для этого?
Моя текущая попытка:
let cacheStorage = {}; // or window.localStorage, but it's beside the point
/**
* @return {!Promise{!State}}
*/
function getStatePromise() {
if (cacheStorage.state !== undefined) {
return Promise.resolve(cacheStorage.state);
}
return new Promise(resolve => {
API.addEventListener(newState => {
cacheStorage.state = newState;
resolve(newState); // ??? what if the listener is called again?
}, /* repeating */ true);
});
}
function doStuff() {
getStatePromise().then(state => {
// my logic
});
}
Когда doStuff()
вызывается в первый раз, cacheStorage
пусто, поэтому getStatePromise()
получит объект State
, заполнит кеш и вернет обещание, которое преобразуется в объект State
. Затем, когда doStuff()
вызывается во второй раз, он просто возвращает обещание, которое разрешается кэшированному объекту State
.
Однако проблема в том, что новый State
становится доступным позже , API
снова вызовет обратный вызов слушателя, что означает, что resolve()
будет снова вызван (см. ???
в коде). Это звучит неправильно, потому что это разрешает обещание, которое уже выполнено. Как мне это исправить?
Изменить: это исправление?
Заменить
return new Promise(resolve => {
API.addEventListener(newState => {
cacheStorage.state = newState;
resolve(newState); // ??? what if the listener is called again?
}, /* repeating */ true);
});
на
return new Promise(resolve => {
let initialCall = true;
API.addEventListener(newState => {
cacheStorage.state = newState;
if (initialCall) {
resolve(newState);
initialCall = false;
}
}, /* repeating */ true);
});