Таймер каждой нажатой кнопки должен запускаться только после завершения предыдущего
Всем хорошего времени суток!
Прошу помочь решить небольшую задачку.
Имеется функциональный компонент, который рендерит 3 кнопки. При нажатии на первую кнопку запускается таймер на 7 секунд и возвращается промис (назовем ее "медленной"). При нажатии на вторую кнопку происходит тоже самое, но промис возвращается через 2 секунды ("быстрая"). Третья кнопка сбрасывает состояние. Далее, в консоль передаются некоторые данные - время нажатия кнопки, количество секунд таймаута и время выведения данных в лог. По отдельности все работает хорошо.
Вопрос: как можно сделать так, что бы данные о нажатии кнопок передавались в консоль не по мере выполнения таймаута для каждого промиса, а в порядке нажатия на эти самые кнопки? Т.е. таймер следующей нажатой кнопки должен запускаться только после завершения предыдущего.
Например: я нажимаю сначала "медленную" кнопку, потом "быструю", но данные "быстрой" кнопки должны выводиться после вывода данных о "медленной" (которая была нажата первой).
Вот код https://codesandbox.io/s/clever-wozniak-wl8lq
Всем огромное спасибо!
import React from "react";
import ReactDOM from "react-dom";
import moment from "moment";
import "./styles.css";
function App() {
const [infoPress, setInfoPress] = React.useState({
time: moment().format("LTS"),
buttonNumber: "5"
});
const delayAndGetRandom = info => {
return new Promise(resolve =>
setTimeout(() => resolve(info), info.buttonNumber * 1000)
);
};
React.useEffect(() => {
const printFiles = async function() {
const press = await delayAndGetRandom(infoPress);
return press;
};
printFiles().then(res =>
console.log(moment().format("LTS"), Number(res.buttonNumber), res.time)
);
});
const clearState = e => {
setInfoPress({
time: "не установлена",
buttonNumber: null
});
};
const handleClick = e => {
e.preventDefault();
clearState();
setInfoPress({
...infoPress,
time: moment().format("LTS"),
buttonNumber: e.target.attributes.getNamedItem("data-key").value
});
};
return (
<>
<button data-key="7" onClick={handleClick}>
Медленно
</button>
<button data-key="2" onClick={handleClick}>
Быстро
</button>
<button onClick={clearState}>Очистить</button>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Ответы (1 шт):
Вот примерная концепция такая.
let queue = Promise.resolve();
function delay(timeout, callback) {
return new Promise((res, rej) =>
setTimeout(() => {
callback(timeout);
res();
}, timeout)
);
}
function onClick(e) {
const timeout = parseInt(e.target.getAttribute("data-delay"));
queue = queue.then(() => delay(timeout, console.log));
}
document.querySelector('.block').addEventListener('click', onClick);
<div class="block">
<button class="btn" data-delay="3000">3000</button>
<button class="btn" data-delay="2000">2000</button>
<button class="btn" data-delay="1000">1000</button>
</div>