Javascript – Uncaught (in promise) TypeError: Cannot read property ‘forEach’ of undefined

apiasync-awaitfetchjavascript

I am trying to fetch data form OMDB database to dispaly movies. Initially I have implemented click event to call data and no errors were found. But when i switch to keyup event i got this error.

Uncaught (in promise) TypeError: Cannot read property 'forEach' of undefined
at fetchMovie.getMovies.then.res (main.js:27)
fetchMovie.getMovies.then.res @ main.js:27
async function (async)
searchInput.addEventListener @ main.js:19

   let searchInput = document.getElementById('search')

    class fetchData {
    constructor() {
        this.apiKey = 'here is APIKey'
    }

    async getMovies(movie) {
        const movieRes = await fetch(`http://www.omdbapi.com/?apikey=${this.apiKey}&s=${movie}`)
        const moveData = await movieRes.json()
        return {
            moveData
        }
    }
      }
    const fetchMovie = new fetchData

    searchInput.addEventListener('keyup', (e) => {
    let input = e.target.value

    if (input !== '') {
        fetchMovie.getMovies(input)
            .then(res => {
                let data = res.moveData.Search
                let output = ''
                data.forEach(movie => {
                    output += `
                    <div class="col-md-3">
                    <div class="card" style="width: 18rem;">
                    <img class="card-img-top" src="${movie.Poster}" alt="Card image cap">
                    <div class="card-body">
                      <h5 class="card-title">${movie.Title}</h5>
                      <p class="card-text">${movie.Year}</p>
                      <a href="#" class="btn btn-primary">Go somewhere</a>
                    </div>
                  </div>
                    </div>`
                });
                document.getElementById('container').innerHTML = output;
            })
    }
    e.preventDefault();
    })

SCEENSHOT

enter image description here

ERROR fixed with empty images also added keyup event. No errors in console

    let searchInput = document.getElementById('search');

class fetchData {

    constructor() {
        this.apiKey = '884df292'
    }

    async getMovies(movie) {
        const movieRes = await fetch(`http://www.omdbapi.com/?apikey=${this.apiKey}&s=${movie}`)
        const moveData = await movieRes.json()
        return {
            moveData
        }
    }
}
const fetchMovie = new fetchData

searchInput.addEventListener('keyup', (e) => {
    let input = e.target.value;

    if (input !== '') {
        fetchMovie.getMovies(input)
            .then(res => {
                let data = res.moveData.Search
                console.log(data)
                if (!data) {
                    return false
                } else {
                    let output = ''
                    data.forEach(movie => {
                        let poster
                        if (movie.Poster === "N/A") {
                            poster = `https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg`
                        } else {
                            poster = movie.Poster
                        }
                        output += `
                    <div class="col-md-3 movie-card">
                    <div class="card">
                    <img class="card-img-top" src="${poster}" alt="Card image cap">
                    <div class="card-body">
                      <h5 class="card-title">${movie.Title}</h5>
                      <p class="card-text">${movie.Year}</p>
                      <a href="#" class="btn btn-primary">Go somewhere</a>
                    </div>
                  </div>
                    </div>`
                    });
                    document.getElementById('container').innerHTML = output;
                }
            })
            .catch(err => console.log(err))
    }
    e.preventDefault();
})

Best Answer

If you see the log screenshot you first get and undefined logged. That is most likely because your fetch happens for each key press, and if you search the API for a single character (which is what you sent with the first keyup) you get back no results and thus the forEach fails.

Either check if data has a value before doing the forEach or don't even send a fetch if the search string is a single character.

let data = res.moveData.Search
let output = ''
if (!data) return; //early break if not results where returned.

or change if (input !== '') { to

if (input.trim().length > 1) { // only do the fetch if more than one characters where entered

although you might still get no results even if you sent more than one characters so the 1st approach is safer.