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}`)
    });
}

5
  • what's the question? is it that you're putting 856 photos all into the one <img> so you only see one? Commented Aug 24, 2022 at 8: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 Commented Aug 24, 2022 at 8:10
  • You want this: jsfiddle.net/80pe5nf6 Commented Aug 24, 2022 at 8:13
  • Oh, well, you don't want to loop then Commented Aug 24, 2022 at 8:23
  • Relevant dupes: stackoverflow.com/questions/48474970/… stackoverflow.com/questions/14004318/… Commented Aug 24, 2022 at 8:23

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

Comments

-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="" />

6 Comments

Fetching the massive JSON again and again seems very bad practice ;)
@ChrisG I agree and I Fixed it
Still, I don't think this is a good contribution. It's basically two questions in one, and of course both are dupes: stackoverflow.com/questions/48474970/… stackoverflow.com/questions/14004318/…
Because it's tiresome.
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!!!
|
-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

1 Comment

oh thank you for the advice, I'm kinda a noob to javascript, I will surely learn along the way
-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)];

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.