fruity4pie
@fruity4pie
A

Почему множественный fetch-запрос возвращает Promise вместо объектов?

  • Вопрос задан
  • 1060 просмотров
Решения вопроса 2
rockon404
@rockon404
Frontend Developer
Promise.all(data).then(console.log);
Ответ написан
Комментировать
AngReload
@AngReload
Кратко о себе
Потому что then всегда возвращает promise.
Даже если ты внутри функции resolve напишешь return 42, это then вернёт Promise(42).
fetch(url).then(function(response) {
  return 42;
})

Это работает так по двум причинам.
Первая, чтобы можно было без проблем писать .then().then().then(). Ведь если какой-нибудь then вернёт число посреди такой цепочки, то произойдёт ошибка. Ведь у чисел нет метода then, верно?
(42).then() // => TypeError: 42.then is not a function
Вторая причина, это то что промисы не выполняются сразу. В этом и смысл, верно? Мы создаём цепочку отложенных вычислений по принципу Если произошло это, тогда сделать То, а потом Вот это и т.д. Методу then просто нечего возвращать на тот момент, когда ты его запускаешь. Его запуск только создаёт план действий.

Поэтому, когда ты запускаешь console.log(data), в массиве data лежат промисы. И они даже ещё не начали выполняться на этот момент. Ни одна из функций resolve или reject еще не была запущена.

Код можно поправить так:
'use strict';

let urls = [
  'https://apiv2.bitcoinaverage.com/indices/global/ticker/ETHUSD',
  'https://apiv2.bitcoinaverage.com/indices/global/ticker/LTCUSD',
  'https://apiv2.bitcoinaverage.com/indices/global/ticker/BTCUSD'
];

let data = urls.map((item, index) => {
  return fetch(item).then(function(response) {
    return response.json();
  }).then(function(data) {
    console.log(data);
  }).catch( alert );
})

console.log(data);
Сначала в консоли появится массив промисов, который ты уже видел. А уже через секунду три объекта, которых ты ждал.

Чтобы получить три объекта сразу, в массиве, нужно прибегнуть к либо async / await, либо как писали в других ответах Promise.all. Promise.all(array).then(resolve, reject) ждет выполнения всех промисов в array, и только тогда вызывает resolve или reject для массива ответов или ошибок.

'use strict';

let urls = [
  'https://apiv2.bitcoinaverage.com/indices/global/ticker/ETHUSD',
  'https://apiv2.bitcoinaverage.com/indices/global/ticker/LTCUSD',
  'https://apiv2.bitcoinaverage.com/indices/global/ticker/BTCUSD'
];
let array = urls.map((item, index) => {
  return fetch(item).then(function(response) {
    return response.json();
  }).catch( alert );
});

Promise.all(array).then(console.log);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы