dev0010
dev0010

Reputation: 95

JavaScript: Returning array from recursive function

I have made a class which builds some data from api:

const http = require("http");

class VideoService {

    constructor() {
        this.items = [];
    }

    fetchVideos(token = "") {

        const url = `https://www.example.com`;

        http.getJSON(url).then((results) => {
            results.items.forEach((item, index) => {
                const vid = item.snippet.resourceId.videoId;

                this.items.push({
                    title: item.title,
                    date: item.publishedAt
                });

                console.log(this.items.length); // here length inreases, works here
            });

            if (typeof results.nextPageToken !== "undefined") {
                return this.fetchVideos(results.nextPageToken);
            }

        });
    }

    getVideos() {
        this.fetchVideos();

        console.log(this.items.length); // this returns 0 instead of all items fetched

        return this.items;
    }

}

module.exports = VideoService;

In another file, I am using it like this:

const videoService = require("../shared/videoService");

const videos = (new videoService()).getVideos();
console.log(videos);

The last console.log call always returns empty array instead of all data collected in items property of the above class.

Can anybody tell what I am missing here?

Upvotes: 1

Views: 76

Answers (1)

lloydaf
lloydaf

Reputation: 605

This happens because in your function fetchVideos(), you are making an http call which will be processed asynchronously. You can try to process it this way.

fetchVideos(token = "") {

    const url = `https://www.example.com`;

    return http.getJSON(url).then((results) => {
        results.items.forEach((item, index) => {
            const vid = item.snippet.resourceId.videoId;

            this.items.push({
                title: item.title,
                date: item.publishedAt
            });

            console.log(this.items.length); // here length inreases, works here
        });

        if (typeof results.nextPageToken !== "undefined") {
            return this.fetchVideos(results.nextPageToken);
        }
        else return new Promise((resolve, reject)=>{
          resolve();
        });

    });
}

getVideos() {
    return this.fetchVideos().then(function(){
       console.log(this.items.length); // this returns 0 instead of all items fetched
    return this.items;
    });
}

I suggest reading about promises and asynchronicity in javascript. Check this link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Upvotes: 1

Related Questions