Иногда бывает, что какая-то операция происходит на бэкенде асинхронно и мы не можем сразу получить ответ. Например, так работает отправка задач на 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"