Как правильно работать с асинхронными функциями
При запросах в интерфейсах мы запрашиваем данные и иногда показываем спиннер, но если запрос выполняется быстро, то его показывать пользователю нету смысла — всё и так готово!
Нужно реализовать подобную логику в асинхронной функции.
На вход подается функция request, которая возвращает Promise. Если она выполняется меньше чем за 250 миллисекунд, то спиннер показывать нет смысла. А если она выполняется дольше, то нужно показать спиннер, при помощи функции showSpinner, который должен крутиться не меньше 1000 миллисекунд и скрыться при помощи функции hideSpinner. Гарантируется, что запрос выполняется не дольше 1000 миллисекунд. Файл с ответом должен экспортировать функцию с тремя параметрами:
/**
* request: () => Promise
* showSpinner: () => void
* hideSpinner: () => void
*/
module.exports = async function (request, showSpinner, hideSpinner) {
// ваш код
}
У функции нет возвращаемого значения, нужно корректно вызвать переданные функции и завершиться.
Ответы (1 шт):
Для решения понадобится вспомогательная функция delay возвращающая Promise
function delay(ms, result) {
return new Promise(r => setTimeout(() => r(result), ms));
}
- первый шаг, воспользоваться функцией
Promise.race, это позволит определить выполнился ли переданный запрос раньше таймаута. - если он выполнился раньше можно сразу вернуть значение
- если выполнился позже
- показать спиннер
- подождать 1000 мс
- скрыть спиннер
- вернуть результат.
Пример:
/**
* request: () => Promise
* showSpinner: () => void
* hideSpinner: () => void
*/
async function doRequest(request, showSpinner, hideSpinner) {
const timeout = {};
const result = request();
const race = await Promise.race([result, delay(250, timeout)]);
if (race == timeout) {
showSpinner();
await delay(1000);
hideSpinner();
}
return result;
}
function delay(ms, result) {
return new Promise(r => setTimeout(() => r(result), ms));
}
function show() {
console.log('show');
}
function hide() {
console.log('hide');
}
function req() {
return delay(100, 'result'); // эмулируем запрос длящийся меньше порога
}
function req2() {
return delay(300, 'result 2'); // эмулируем запрос длящийся дольше порога
}
(async() => {
console.log(await doRequest(req, show, hide));
console.log(await doRequest(req2, show, hide));
})()