Как правильно работать с асинхронными функциями

Рейтинг: 0Ответов: 1Опубликовано: 02.03.2023

При запросах в интерфейсах мы запрашиваем данные и иногда показываем спиннер, но если запрос выполняется быстро, то его показывать пользователю нету смысла — всё и так готово!

Нужно реализовать подобную логику в асинхронной функции.

На вход подается функция request, которая возвращает Promise. Если она выполняется меньше чем за 250 миллисекунд, то спиннер показывать нет смысла. А если она выполняется дольше, то нужно показать спиннер, при помощи функции showSpinner, который должен крутиться не меньше 1000 миллисекунд и скрыться при помощи функции hideSpinner. Гарантируется, что запрос выполняется не дольше 1000 миллисекунд. Файл с ответом должен экспортировать функцию с тремя параметрами:

/**
* request: () => Promise
* showSpinner: () => void
* hideSpinner: () => void
*/
module.exports = async function (request, showSpinner, hideSpinner) {
  // ваш код
}

У функции нет возвращаемого значения, нужно корректно вызвать переданные функции и завершиться.

Ответы

▲ 0

Для решения понадобится вспомогательная функция delay возвращающая Promise

function delay(ms, result) {
  return new Promise(r => setTimeout(() => r(result), ms));
}
  1. первый шаг, воспользоваться функцией Promise.race, это позволит определить выполнился ли переданный запрос раньше таймаута.
  2. если он выполнился раньше можно сразу вернуть значение
  3. если выполнился позже
    1. показать спиннер
    2. подождать 1000 мс
    3. скрыть спиннер
  4. вернуть результат.

Пример:

/**
 * 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));
})()