0

I'm trying to access the image property from the array of objects from NASA API , so it can be displayed randomly when I click on a button

I want a different image to be shown whenever I click a button. The images are from an array of objects from NASA api.

document.querySelector('button').addEventListener('click', getFetch)
function getFetch() {
  const url = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=1wCuyjoxfSrvsEbUpfWJvuBEMB5I0x79kXS0pfrg'
  fetch(url)
    .then(res => res.json()) // parse response as JSON
    .then(data => {
      console.log(data)
      data.photos.forEach(element => {
        document.querySelector('img').src = element.img_src
        f
      });

    })
    .catch(err => {
      console.log(`error ${err}`)
    });
}
mplungjan
  • 169,008
  • 28
  • 173
  • 236
okani
  • 3
  • 1
  • what's the question? is it that you're putting 856 photos all into the one `` so you only see one? – Jaromanda X Aug 24 '22 at 08:04
  • No, I'm trying to access one of each image from the 856 photos each time I click the button. I want it to show a different image. @JaromandaX – okani Aug 24 '22 at 08:10
  • You want this: https://jsfiddle.net/80pe5nf6/ –  Aug 24 '22 at 08:13
  • Oh, well, you don't want to loop then – Jaromanda X Aug 24 '22 at 08:23
  • Relevant dupes: https://stackoverflow.com/questions/48474970/saving-fetched-json-into-variable https://stackoverflow.com/questions/14004318/show-random-image-from-array-in-javascript –  Aug 24 '22 at 08:23

4 Answers4

0

I'd say that you are doing it the wrong way around - don't fetch up to 1000 images on click, fetch them first and cycle through them on click.

const button = document.querySelector('button');
const img = document.querySelector('img');
const imgUrl = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=1wCuyjoxfSrvsEbUpfWJvuBEMB5I0x79kXS0pfrg'

const makeImgCycler = (images) => {
  return () => {
    const n = Math.floor(Math.random() * images.length);
    return images[n];
  };
};

const fetchImgs = (url) => {
  return fetch(url).then(r => r.json());
};

fetchImgs(imgUrl).then(data => {
  const nextImage = makeImgCycler(data.photos);
  button.disabled = null;
  button.addEventListener('click', () => {
    img.src = nextImage().img_src;
  });
});
<button disabled>Next</button>
<img alt="">

Hint
The "Next" button is initially disabled until the images are loaded.

EDIT
Made makeImgCycler/nextImage return a random image. Not checking if it returns the same random image on subsequent clicks, though.

David
  • 3,552
  • 1
  • 13
  • 24
-1

This is not fast so we fetch first and then allow showing

I have now implemented that we show unique random images until we have shown all, then we again show unique random images from a copy of the original array.

const randomImage = document.getElementById("randomImage");
const btn = document.querySelector('button');
const url = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=1wCuyjoxfSrvsEbUpfWJvuBEMB5I0x79kXS0pfrg'
let shown = [];
let images = [];
const getUnique = () => {
  if (images.length === 0) images = shown.splice(0, shown.length); // copy back
  const rnd = Math.floor(Math.random() * images.length);
  const image = images.splice(rnd, 1)[0];
  shown.push(image)
  return image;
};
fetch(url)
  .then(res => res.json()) // parse response as JSON
  .then(data => {
    images = data.photos.map(element => element.img_src) // .slice(0, 3); // for testing
    btn.textContent = "Show image";
    btn.addEventListener('click', function() {
      randomImage.src = getUnique();
    })
  })
  .catch(err => {
    console.log(`error ${err}`)
  });
<button type="button">Please wait...</button>

<img id="randomImage" src="" />

Previous simpler version

const randomImage = document.getElementById("randomImage");
const btn = document.querySelector('button');
const url = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=1wCuyjoxfSrvsEbUpfWJvuBEMB5I0x79kXS0pfrg'
fetch(url)
  .then(res => res.json()) // parse response as JSON
  .then(data => {
    let images = data.photos.map(element => element.img_src);
    btn.textContent = "Show image";
    btn.addEventListener('click', function() {
      const rnd = Math.floor(Math.random() * images.length);
      randomImage.src = images[rnd];
    })
  })
  .catch(err => {
    console.log(`error ${err}`)
  });
<button type="button">Please wait...</button>

<img id="randomImage" src="" />
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • 1
    Fetching the massive JSON again and again seems very bad practice ;) –  Aug 24 '22 at 08:14
  • @ChrisG I agree and I Fixed it – mplungjan Aug 24 '22 at 08:21
  • Still, I don't think this is a good contribution. It's basically two questions in one, and of course both are dupes: https://stackoverflow.com/questions/48474970/saving-fetched-json-into-variable https://stackoverflow.com/questions/14004318/show-random-image-from-array-in-javascript –  Aug 24 '22 at 08:23
  • Because it's tiresome. –  Aug 24 '22 at 08:25
  • Thank you guys, I've found the soulution – okani Aug 24 '22 at 08:59
  • 1
    WOW @mplungjan This is much simpler to understand, I'm sorry I didnt see it earlier, Thank you for showing this to me, Thank you!!! – okani Aug 24 '22 at 10:15
-2

First of all, please remove your API keys when posting to public forums.

The reason is that you are applying the image url to the same image object and so the last image to be iterated will be the one displayed. My recommendation would be to cache the images in an array somewhere and then choose a new random image when you click the button again.

The API should not have to be called more than once since it's making a HTTP request and will feel slow and sluggish depending on the distance from the user and the NASA servers

KibbeWater
  • 174
  • 1
  • 10
  • oh thank you for the advice, I'm kinda a noob to javascript, I will surely learn along the way – okani Aug 24 '22 at 08:59
-3

Your API is providing object array. If you want to show random image from an array you can use some like below:

let show = photos[Math.floor(Math.random() * photos.length)];

Himanshu
  • 103
  • 1
  • 5