Pull to refresh

Comments 24

Если в цифрах, то размер axios составляет 371 Кб, а размер very-simple-fetch — 9.33 Кб.
Но ведь это всё gzip'ом отдают. В таком случае он вряд ли будет больше 10 kB.

спасибо за уточнение

Вопрос - fetch() сложный? Куда уж проще... Ладно колбеки в XMLHttpRequest не нравились, вот вам промис готовый, нет надо лишний траффик, чтобы обертку накатить.

Ну ладно, а в чем преимущество перед наивным fetch ()? Вообще не понял

Если говорить про axios, то преимуществ ощущается несколько:

  1. Единый код для node и browser

  2. Возможность установки настроек для instance. Вроде baseUrl, заголовков, которые должны передавать с каждым запросом (тот же Authorization)

  3. Есть interceptors.

Можно это сделать самому вокруг того же fetch, что и сделал автор статьи для своего проекта.

Моё мнение с Вашим совпало: "Можно это сделать самому вокруг того же fetch, что и сделал автор статьи для своего проекта."

simpleFetch.cancel() очень странно работает в случае нескольких параллельных запросов. Получается, что он отменит их все сразу. Правильнее было бы сделать какой-то более гранулярный контроль.

И еще пара рационализаторских предложений:

  1. Для собирания baseUrl можно было взять нативное API: new URL(options.url, baseUrl)

  2. Для параметров тоже есть нативный URLSearchParams

P.S. и совсем маленькое замечание – сократили вы бы пост в два раза, в ценности бы он совсем не потерял. Не обязательно комментировать каждую строку кода, можно только про самое важное рассказать.

Спасибо за рационализаторские предложения.

2) Поправил

if (options?.params) {
    url = `${url}?${new URLSearchParams(options.params)}`
  }

1) new URL() не будет работать в случае передачи url без ведущего /, а также в случае передачи в качестве url параметров строки запроса.

3) добавил возможность безопасной отмены параллельных запросов:

// будет отменен последний отправленный запрос
simpleFetch.cancel()

// отправляем запрос
simpleFetch(url)
// извлекаем его id
const { currentRequestId } = simpleFetch
// отменяем этот запрос
simpleFetch.cancel(currentRequestId)

Добавили возможность отмены запросы и сделали ошибку в коде.
У вас есть подсветка в редакторе?

const generateRequestId = () => {
  const requestId = Math.random().toString(16).slice(2)
  if (simpleFetch.abortControllers[requestId]) {
    return getRequestId()
  }
  simpleFetch.abortControllers[requestId] = new AbortController()
  simpleFetch.currentRequestId = requestId
  return requestId
}

Где в коде функция getRequestId?

А мне, новичку, с опытом 0 и даже минус очень нужны такие комментарии.

Полезно (и просто) добавить нормальный chaining, вместо затычек вроде вашего authToken.

Патч выше с currentRequestId небезопасен, лучше уж добавить событие onRequest и создавать его там. Что-то вроде

const api = fetcher({...options, authToken, baseUrl}, request => {
	request.on(2000, request.cancel)
})

await api.get('data')

в чем состоит небезопасность?

С небезопасностью ошибся, но в целом полагаться на неизменность currentRequestId не очень хорошо

И бессмысленно с await simpleFetch(url)

посмотрел, не впечатлен

"Сын маминой подруги". Полностью дублирует интерфейс Axios и весит меньше вашей библиотеки.

Никогда не понимал зачем люди тащат в 2021г в свои проекты axios или подобные либы. В каждом проекте одна из первых задач, которую я решаю это создание двух слоёв архитектуры:


  • Слой http (название от балды), где зарыта вся специфика работы с конкретным бакендом. JSON | XML? JWT? Кастомные заголовки? Какой формат у ошибок? CORS? Есть ли специфические заголовки в response? И так далее. Ключевой момент — оно всегда одинаковое для адекватного сервера (если проект пишет не безумец). Так что это слой неизбежен и предельно очевиден
  • Слой api, который под капотом работает с вышеописанным http. Этот слой ничего не знает о вашей бизнеслогике. Просто служит прослойкой между сервером и вашим приложением. Здесь можно подключить нужные io-ts валидаторы. Здесь можно трансформировать данные из какого-нибудь неудобного формата в удобный и наоборот. Здесь можно запустить несколько запросов в параллели. Но самое главное что вся эта мишура лежит внутри этого слоя и не выглядывает наружу. Т.е. здесь будет условный export const apiLoginUser = (userName: string, password: string): Promise<AccessTokens/>. Никакой сетевой требухи. Этот же слой можно mock-ать для тестов и обходится вообще без сервера, если нужно.

В итоге в приложении используются уже максимально упрощённые promise-based методы. Никаких fetch/axios/whatever обвязок. И тут возникает главный вопрос — а зачем при такой архитектуре axios? Чтобы не писать в единственном месте в приложении .then(response => response.json()) и сделать проверку на .statusCode? Серьёзно?


Было бы интересно послушать противоположное мнение.

Удваиваю предыдущего оратора. Принципиально выиграть ничего не удалось. Мы как работали с http, так и продолжаем работать с http. Просто через обёртку

Начал смотреть код снизу - и сразу в первом же методе, видимо, пропущен method: 'DELETE' при передаче одного объекта опций.

Задать методы вроде .delete и подобных можно чем-то вроде

const createMethod = (method, hasBody) => (...args) => simpleFetch({
  method,
  url: typeof args[0] == 'string' ? args.shift() : undefined,
  body: hasBody && args.shift(),
  ...args.shift(),
})

simpleFetch.get = createMethod('GET')
simpleFetch.post = createMethod('POST', true)
simpleFetch.update = createMethod('PUT', true)
simpleFetch.delete = createMethod('DELETE')

и это сэкономит строк 40.

Использование конструктора и объектов URL сильно упростит и улучшит работу.

Глобальные настройки - зло. Предположим, данную библиотеку используете не только вы, но и кто-то ещё, тоже задает baseUrl и authToken и все ломает. У axios на такой случай есть разные инстансы.

Sign up to leave a comment.