#javascript #json #reactjs
#javascript #json #reactjs
Вопрос:
Я хочу получить данные из массива, который включает в себя API внутри, проблема в том, что количество api внутри массива иногда отличается от других.
{
"name": "CR90 corvette",
"model": "CR90 corvette",
"manufacturer": "Corellian Engineering Corporation",
"cost_in_credits": "3500000",
"length": "150",
"max_atmosphering_speed": "950",
"crew": "30-165",
"passengers": "600",
"cargo_capacity": "3000000",
"consumables": "1 year",
"hyperdrive_rating": "2.0",
"MGLT": "60",
"starship_class": "corvette",
"pilots": [],
"films": [
"http://swapi.dev/api/films/1/",
"http://swapi.dev/api/films/3/",
"http://swapi.dev/api/films/6/"
],
"created": "2014-12-10T14:20:33.369000Z",
"edited": "2014-12-20T21:23:49.867000Z",
"url": "http://swapi.dev/api/starships/2/"}
В приведенном выше коде json поле Films — это массив, который я имею в виду, например, в этих данных Films содержит 3 данные в виде адресов API, в других данных у них есть 2 данные адресов API и так далее.
Мой вопрос в том, как я могу вызвать API внутри массива таким образом, и как я могу вызвать все адреса API внутри одновременно?
Спасибо, что нашли время прочитать это, слава.
Комментарии:
1. что вы подразумеваете под вызовом? Вы имеете в виду асинхронный вызов?
2.
Promise.all
вероятно, это то, что вы хотите.
Ответ №1:
Есть много способов сделать это. Следующий код отправляет запросы на данные фильма в быстрой последовательности, а затем используется Promise.all
для ожидания их возврата, прежде чем продолжить. Обратите внимание, что это Promise.all
приведет к быстрому сбою, если один запрос выдает исключение. Используйте Promise#allSettled
, если вы хотите замедлить работу.
const data = { films: [ 'http://example.com/1', 'http://example.com/2', 'http://example.com/3' ]}
const { films: urls } = data
const promises = []
for(let url of urls)
promises.push(fetch(url))
Promise.all(promises)
.then((filmDetails) => {
for(let details of filmDetails)
console.log(filmDetails)
})
Ответ №2:
Вы можете использовать async
await
amp; затем использовать fetch
для выполнения вызова api.
let data = {
"name": "CR90 corvette",
"model": "CR90 corvette",
"manufacturer": "Corellian Engineering Corporation",
"cost_in_credits": "3500000",
"length": "150",
"max_atmosphering_speed": "950",
"crew": "30-165",
"passengers": "600",
"cargo_capacity": "3000000",
"consumables": "1 year",
"hyperdrive_rating": "2.0",
"MGLT": "60",
"starship_class": "corvette",
"pilots": [],
"films": [
"https://swapi.dev/api/films/1/",
"https://swapi.dev/api/films/3/",
"https://swapi.dev/api/films/6/"
],
"created": "2014-12-10T14:20:33.369000Z",
"edited": "2014-12-20T21:23:49.867000Z",
"url": "http://swapi.dev/api/starships/2/"
};
async function fncGetResult(arr) {
let val = [];
for (let i = 0; i < arr.length; i ) {
const res = await fetch(arr[i]).then(d => d.json()).then(d =>d);
val.push(res)
};
return val;
}
fncGetResult(data.films).then((result) => {
console.log(result)
})
Комментарии:
1. Это приведет к последовательному выполнению запросов, я думаю
promise.all
, что это гораздо лучший вариант для использования здесь, потому что каждый HTTP-запрос не зависит от других запросов.2. я только что попробовал ваш код, и он работает, но затем я получаю сообщение об ошибке «Необработанное отклонение (TypeError): arr не определено», как я могу это исправить?
3. @brk я поместил свой полный код здесь codeshare.io/starship
4. @brk некоторый массив, содержащий адреса API
5. Попробуйте вызвать, как это
axios.get(
swapi.dev/api/starships/ $ {id}/).then((result) => { setDetail(result.data); fncGetResult(result.data.films) });
Ответ №3:
Вы можете использовать функцию map
из пакета async.
Async — это служебный модуль, который предоставляет простые, мощные функции для работы с асинхронным JavaScript. Хотя изначально предназначался для использования с Node.js и устанавливаемый через npm i async, он также может быть использован непосредственно в браузере.
Первый параметр — это ваш массив, который вы можете удалить из своего объекта, второй — вызов вашего api или любой другой асинхронной функции (здесь я использую axios
package , но вы можете вызвать api только с помощью собственного пакета узла http
), а третий — функция обратного вызова, которая может обеспечить вам проверку успешной работы.
import async from 'async'
import axios from 'axios'
const obj = {
name: "CR90 corvette",
films: [
"http://swapi.dev/api/films/1/",
"http://swapi.dev/api/films/3/",
"http://swapi.dev/api/films/6/"
]
}
const { films } = obj
const responses = async.map(
films,
(url, callback) => {
try {
axios.get(url)
callback(null, 'OK')
} catch (error) {
callback(error)
}
}, (error, result) => {
if (error) {
console.log(error)
}
console.log(result)
}
)