1

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?

6
  • 1
    Yeah so your function fetchVideos() has an http call which will be processed asynchronously. I suggest using something like a Promise or an Observable. You can read more about Promises here. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Nov 22, 2018 at 13:52
  • To elaborate: the calls to .getJSON() return immediately, before the response to the underlying HTTP request has been received. Commented Nov 22, 2018 at 13:53
  • @Pointy: Thanks but I am rather new to promises stuff I cannot understand how to modify this code to use promises. I will love to see fix in an answer so I can accept it. Thanks Commented Nov 22, 2018 at 13:55
  • Your main issue is that you're not return a (resolved) Promise at the end of the recursion. Commented Nov 22, 2018 at 14:00
  • Maybe the following answer can help you out in making requests based on result of previous request. Commented Nov 22, 2018 at 14:02

1 Answer 1

1

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

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

4 Comments

This is a good start, but things are much complicated by the fact that further HTTP requests are initiated in the callback in fetchVideos().
@Pointy nice catch. I did not notice that before.
@LloydFrancis: It still does not work as expected, console.log does not show any results.
The fetchVideos function is failing to return a Promise at the end of the chain of recursive calls

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.