217. Асинхронное получение данных

Не решаласьСредняя

Ваш друг Лёша работает продакт-менеджером, для принятия грамотных продуктовых решений, ему каждый день нужно аналитику с нескольких сайтов у которых есть открытый API. Чтобы не делать это вручную, Леша просит вас помочь написать ему функцию для получения всех данных разом. Причем некоторые сайты аналитики могут возвращать битые данные, а так же сервера из-за нагрузки могут переодически не отвечать.

Для решения этих проблем Леша предлагает следующее:

  • Для обхода проблем с сетью реализовать логику перезапроса данных.
  • Во избежание проблем с целостностью данных сравнивать хеш-сумму, полученную из запроса, с той, которую мы вычислим на нашей стороне с помощью асинхронной функции getHashByData. Если хеш-суммы не совпадут, попробуйте перезапросить данные с сервера.
  • Чтобы не перегружать сервера постоянными перезапросами, нужно уметь устанавливать лимит на количество перезапросов к одному API, который можно будет задать как параметр функции.
  • Если информацию из какого-то API получить не удалось, мы его не включаем в результат.

Примечания

Заранее определены 2 функции: fetchData и getHashByData, которые понадобятся вам для решения и их нужно импортировать с помощь require из модуля ./utils(Можно увидеть в шаблоне решения).

Функция fetchData

Это асинхронная функция, которую следует использовать для запросов к API:

  • принимает один аргумент: url
  • возвращает Promise, который при успешном запросе вернет вам объект c двумя полями data и hashSum.

Типы функции на JSDoc

/**
 * @typedef FetchResult
 * @type {object}
 * @property {string} data - данные которые вернуло API.
 * @property {string} hashSum - хеш-сумма данных.
 */

/**
 * @param {string} url - url с которого следует получить данные.
 * @return {Promise<FetchResult>}.
 */
function fetchData(url) {
  //...
};
Функция getHashByData

Это асинхронная функция, которую следует использовать для получения хеша от данных:

  • принимает 2 аргумента: данные и колбэк-функцию.
  • как только будет вычислен хеш от данных, вызывает колбэк-функцию и передает его первым параметром.
  • ничего не возвращает.

Типы функции на JSDoc

/**
 * Ожидаемая сигнатура колбэк-функции.
 * @callback calculateHashCallback
 * @param {string} hash - вычисленный хеш, от данных.
 */

/**
 * @param {string} data - данные от которых следует вычислить хеш.
 * @param {calculateHashCallback} cb - коллбэк-функция, в которую будет передан вычисленный хеш.
 */
function getHashByData(data, cb) {
  //...
};
Шаблон решения для отправки

Решите эту задачу на JavaScript (ES2017) и оформите решение по шаблону:

const {getHashByData, fetchData} = require('./utils');

module.exports = async function(urls, retryCount) {
    // code here
}
Playground

По ссылке можно скачать архив с окружением в котором вы сможете потестировать свое решение.

Формат ввода

Ваша функция должна принимать 2 параметра:

  • массив строк url.
  • количество перезапросов, которое мы можем сделать.

Формат вывода

Полученные данные должны возвращаться в виде массива. Если информацию из какого-то API получить не удалось, мы его не включаем в результат.

Пример
/**
 * Описание возвращаемых функцией fetchData данных. Хеш всегда корректен.
 *
 * fetchData('metrika.ru/api/analitics') -> Promise<{data: 'Metrika data', hashSum: '#correctHash'}>
 * fetchData('google.ru/api/analitics') -> Promise<{data: 'Google analytics data', hashSum: '#correctHash'}>
 * 
 * fetchData('badhost-analitics.com/api/analitics') -> Сервер постоянно не доступен
 *
 * solution - ваше решение.
 */


// Позитивный
solution(['metrika.ru/api/analitics', 'google.ru/api/analitics'], 4)
 .then(data => console.log(data)) // ['Metrika data', 'Google analytics data']

// Негативный
solution(['google.ru/api/analitics', 'badhost-analitics.com/api/analitics', 'metrika.ru/api/analitics'], 4)
 .then(data => console.log(data)) // ['Google analytics data', 'Metrika data']

Вердикт IL означает, что вы неоптимально выполняете запросы и не укладываетесь в ограничение по времени.

Ограничения

Ограничение времени

1 с

Ограничение памяти

64 МБ

Пример 1

Ввод
// Позитивный сценарий без перезапросов
module.exports = [
	// urls
	[
    	'metrika.ru/api/analitics', // возвращает {data: 'Metrika data', hashSum: #correctHash}
    	'google.ru/api/analitics' // возвращает {data: 'Google analytics data', hashSum: #correctHash}
	],
	// retry count
	3
]
Вывод
["Metrika data","Google analytics data"]

Пример 2

Ввод
// Кейс с неработающим сервером
module.exports = [
	[
		'metrika.ru/api/analitics',
		'badhost-analitics.com/api/analitics'
	],
	3
]
Вывод
["Metrika data"]

Теги

JavaScript Node.js 12
Нужно войти, чтобы отправить решение.Войти