Я ищу шаблон для решения типичной проблемы, когда несколько (пользовательских) событий запускаются вскоре после друг друга, и каждое событие должно заботиться о некоторой большой нагрузке, которая должна быть обработана до конца перед новым событием.может быть принят.
Типичным вариантом использования может быть, например, список элементов, по которым пользователь может щелкнуть, и для каждого элемента требуется некоторая асинхронная загрузка и обработка.Пользователь нажимает на элемент, который запускает асинхронную обработку.Когда событие обрабатывается, новая обработка не должна начаться, когда выбран другой элемент, и в лучшем случае (производительность) должна обрабатываться только последнее событие.
Следующий фрагмент кода имитирует сценарий использования ивывод консоли показывает, как событие возникает, а затем обрабатывается.Функция run
моделирует (пользовательские) события, а функция heavyLifting
моделирует некоторую асинхронную тяжелую атлетику.Обрабатывается больше событий, чем необходимо, и, убедившись, что функция heavyLifting
вызывается только последовательно с использованием семафора currentlyLifting
, также больше не гарантируется, что по крайней мере самое последнее событие всегда обрабатывается.
Используйте JSFiddle для запуска отсканированного кода
const getRandom = (min, max) => Math.floor(Math.random() * (max - min) + min);
const heavyLifting = id => {
return new Promise(resolve => {
const cost = getRandom(500, 750)
console.log(`heavy lifting "${id}" with cost "${cost}" started...`);
setTimeout(() => {
console.log(`heavy lifting "${id}" completed.`);
resolve();
}, cost);
});
};
let currentlyLifting;
window.addEventListener('heavyLift', async (e) => {
const id = e.detail.id;
if (currentlyLifting !== undefined) {
console.log(`cannot start new heavy lifting of "${id}" while still running "${currentlyLifting}"`);
} else {
currentlyLifting = id;
await heavyLifting(id);
currentlyLifting = undefined;
}
});
const run = () => {
let id = 1;
const timerCallback = () => {
console.log(`dispatchEvent "${id}"`);
window.dispatchEvent(new CustomEvent('heavyLift', {detail: {id}}));
if (id++ < 10) {
setTimeout(timerCallback, 100);
}
};
timerCallback();
};
run();
<!DOCTYPE html>
<html>
<body>
<script src="index.js"></script>
</body>
</html>