0

I want to use a json to read my videos and then display them using ejs, but I get an error:

>> 320|             <% video.videos.forEach(function(video) { %>
video is not defined

I've used the same approach for the items.json and I did not have this problem, if needed I can upload the code for displaying the items and the items.json too.
HTML:

<ul class="splide__list">
            <% video.videos.forEach(function(video) { %>
            <li class="splide__slide">
              <a href="<%= video.href %>" data-lity>
                <img class="thumbnail" data-splide-lazy="<%= video.src %>" alt="<%= video.alt %>">
              </a>
              <p><%= video.desc %></p>
            </li>
            <% }) %>
          </ul>

Node js:

app.all('/', function (req, res) {
    var items, videos;
    //read shop items
    fs.readFile('items.json', function (err, data) {
        if (err) {
            res.status(500).end();
        } else {
            items = JSON.parse(data);
        }
    });
    // read videos
    fs.readFile('video.json', function (err, data) {
        if (err) {
            res.status(500).end();
        } else {
            videos = JSON.parse(data);
        }
    });
    
        res.render('index.ejs', {
            items: items,
            videos: videos
       });
    
});

My video.json:

{
    "videos":[
        {
            "href":"media/video.mp4",
            "src":"thumbnails/thumbnail2.png",
            "alt":"video with 1",
            "desc":"desc1"
        },
        {
            "href":"media/video3.mp4",
            "src":"thumbnails/thumbnail3.png",
            "alt":"video with 2",
            "desc":"desc2"
        }
    ]
}
al21
  • 39
  • 5
  • Typo: You pass the EJS `videos` but you try to read `video`. – Quentin May 07 '21 at 09:49
  • Oh, and they are undefined too: https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Quentin May 07 '21 at 09:50

1 Answers1

1

The problem is that fs.readFile is async, whereas you call the render function without waiting for them, so you have no warranty that you will have the content read into memory. To solve the problem you can either move your render call into callback or use async/await to handle async code. I will show you the example with async/await.

app.all('/', function (req, res) {
    try {
        const items = await fs.promises.readFile('items.json').then(JSON.parse);
        const videos = await fs.promises.readFile('videos.json').then(JSON.parse);
        res.render('index.ejs', { items, videos });

    } catch (e) {
        res.status(500).end();
    }
});

And yes you are passing videos whereas in template you access the video variable so change that to the videos too.

Ayzrian
  • 2,279
  • 1
  • 7
  • 14
  • Thank you. The main problem was how I was reading the files, using await did the trick. And of course, the variable names. – al21 May 07 '21 at 10:39