0

Here is a sample of the data that I have after pushing two JSON objects into an array. Accessing the data is simple. If I wanted to access say the logo, I could use example[0].channels.logo. However, when attempting to access the same array from a JSONP call, the result is undefined.

let example =
[
    {
    "channels": {
        "mature": false,
        "status": "Some GoLang Today #go #golang #youtube",
        "broadcaster_language": "en",
        "display_name": "FreeCodeCamp",
        "game": "Creative",
        "language": "en",
        "_id": 79776140,
        "name": "freecodecamp",
        "created_at": "2015-01-14T03:36:47Z",
        "updated_at": "2018-04-11T22:33:06Z",
        "partner": false,
        "logo": "https://static-cdn.jtvnw.net/jtv_user_pictures/freecodecamp-profile_image-d9514f2df0962329-300x300.png",
        "video_banner": "https://static-cdn.jtvnw.net/jtv_user_pictures/freecodecamp-channel_offline_image-b8e133c78cd51cb0-1920x1080.png",
        "profile_banner": "https://static-cdn.jtvnw.net/jtv_user_pictures/freecodecamp-profile_banner-6f5e3445ff474aec-480.png",
        "profile_banner_background_color": null,
        "url": "https://www.twitch.tv/freecodecamp",
        "views": 210806,
        "followers": 11582,
        "_links": {
        "self": "https://api.twitch.tv/kraken/channels/freecodecamp",
        "follows": "https://api.twitch.tv/kraken/channels/freecodecamp/follows",
        "commercial": "https://api.twitch.tv/kraken/channels/freecodecamp/commercial",
        "stream_key": "https://api.twitch.tv/kraken/channels/freecodecamp/stream_key",
        "chat": "https://api.twitch.tv/kraken/chat/freecodecamp",
        "features": "https://api.twitch.tv/kraken/channels/freecodecamp/features",
        "subscriptions": "https://api.twitch.tv/kraken/channels/freecodecamp/subscriptions",
        "editors": "https://api.twitch.tv/kraken/channels/freecodecamp/editors",
        "teams": "https://api.twitch.tv/kraken/channels/freecodecamp/teams",
        "videos": "https://api.twitch.tv/kraken/channels/freecodecamp/videos"
        },
        "delay": null,
        "banner": null,
        "background": null
      }
    },
    {
    "streams": {
        "stream": null,
        "_links": {
        "self": "https://api.twitch.tv/kraken/streams/freecodecamp",
        "channel": "https://api.twitch.tv/kraken/channels/freecodecamp"
        }
      }
    }
]

// all of these work
console.log(example);
console.log(example[0]);
console.log(example[0].channels);
console.log(example[0].channels);

Here is the function that handles each JSONP request - each response is stored in an object with property name of the defined route argument.

const jsonpCall = (route, channel) => {
    let result = {};
    $.ajax({
        url: `https://wind-bow.gomix.me/twitch-api/${route}/${channel}?callback=?`,
        dataType: 'jsonp',
        success: function(data){
            result[route] = data;
        },
    });
    return result;
};

This is the function call that groups two returned objects into one array, and then hands off that array for another function to sort through/reduce to an object.

const channelsToSearch = ["freecodecamp","nba","shroud"];

channelsToSearch.forEach(channel => {
    const channelData = [];
    channelData.push(jsonpCall("channels",channel));
    channelData.push(jsonpCall("streams",channel));
    console.log(sortData(channelData));
});

This is where the problem begins. This function takes the array of two objects, and begins working on creating a new object to return. It can't access the object.

const sortData = arr =>  {
    console.log(arr); // okay!
    console.log(arr[0]); // okay!
    console.log(arr[0].channels); // undefined?
    const obj = {};
    obj.logo        = arr[0].channels.logo;
    obj.displayName = arr[0].channels["display_name"];
    arr[1].streams.stream === null ? obj.status = "Offline" : obj.status = arr[1].streams.stream.channel.status;
    return obj;
};

I'm not sure what to discern from the differences in the logs. The first three logs are from the example logs. The last three logs are from the sortData function. The final error is from the obj.logo = arr[0].channels.logo; line in the sortData function.

Logs

  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – CBroe Apr 12 '18 at 07:17

1 Answers1

0

The problem of this code lies in this part:

const jsonpCall = (route, channel) => {
    let result = {};
    $.ajax({
        url: `https://wind-bow.gomix.me/twitch-api/${route}/${channel}?callback=?`,
        dataType: 'jsonp',
        success: function(data){
            result[route] = data;
        },
    });
    return result;
};

The ajax call is asynchronous but it is treated as synchronous. That's why it will return a result of {} since the success function is executed late. If you try to add a console.log inside success function, you will see that it will appear after the logs inside sortData. This is why in your logs, it displayed Array [{}, {}] which are both empty.

One approach to solve this is by coding it asynchronusly:

Make sure jsonpCall returns a Promise. By default $.ajax() returns a Promise.

In this part of the code:

channelsToSearch.forEach(channel => {
    const channelData = [];
    channelData.push(jsonpCall("channels",channel));
    channelData.push(jsonpCall("streams",channel));
    console.log(sortData(channelData));
});

You will have to handle it asynchronusly by using .then callbacks.

Please see this fiddle: https://jsfiddle.net/kLnsf1gn/2. I have added comments in it for easier understanding.

jmarioste
  • 768
  • 7
  • 8