Асинхронный JavaScriptЗапуск асинхронных функцийmedium

Regular Polling

Иногда бывает, что какая-то операция происходит на бэкенде асинхронно и мы не можем сразу получить ответ. Например, так работает отправка задач на maxcode.dev

Вы отправляете задачу, сервер ее тестирует, а через некоторое время вы видите результаты тестов. При этом непонятно, когда результат будет готов. Поэтому фронтенд раз в секунду делает запрос на бэкенд, спрашивая, какой на данный момент результат.

Допустим, если результат не готов, бэкенд отвечает таким объектом:

const testingResponse = { status: "testing", };

Если тесты прошли, то таким объектом:

const okResponse = { status: "done", results: [ { name: "Тест #1 ...", ok: true }, { name: "Тест #2 ...", ok: true }, ] };

Или может случиться TIME LIMIT, когда вы запустили бесконечный цикл. Тогда будет такой ответ:

const timeLimitResponse = { status: "timeLimit", };

Ваша задача — реализовать такое поведение. Конечно, хотелось бы написать код так, чтобы логика повторных запросов была отделена от бизнес-логики конкретного сервиса.

Таким образом нужно написать функцию polling, которая раз в ms миллисекунд будет делать запрос с помощью асинхронной функции fetcher (без аргументов), пока функция isCompleted не вернет true для очередного ответа.

После этого нужно вернуть результат последнего вызова. Если при каком-то вызове случился reject, нужно подождать ms миллисекунд и попробовать снова.

Пример использования

Допустим, первые три раза функция fetcher возвращает объект testingResponse, а на четвертый вызов придет timeLimitResponse.

const testingResponse = { status: "testing" }; const timeLimitResponse = { status: "timeLimit" }; let i = 0; const fakeFetcher = async () => { return i++ < 3 ? testingResponse : timeLimitResponse; } const result = polling( fakeFetcher, (response) => response.status !== "testing", 500, ); result.then(data => console.log(data)); // через 1.5 секунды получим объект со статусом "timeLimit"