无法从jQuery JSONP调用(JavaScript)访问对象

时间:2018-04-12 01:56:59

标签: javascript jquery json ajax object

以下是将两个JSON对象推入数组后的数据示例。访问数据很简单。如果我想访问说明徽标,我可以使用example[0].channels.logo。但是,尝试从JSONP调用访问同一个数组时,结果为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);

这是处理每个JSONP请求的函数 - 每个响应都存储在一个对象中,其属性名称为已定义的路由参数。

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;
};

这是一个函数调用,它将两个返回的对象分组到一个数组中,然后将该数组移交给另一个函数以对对象进行排序/缩小。

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

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

这就是问题的开始。此函数获取两个对象的数组,并开始创建要返回的新对象。它无法访问该对象。

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;
};

我不确定从日志中的差异中辨别出什么。 前三个日志来自示例日志。 最后三个日志来自sortData函数。 最终错误来自sortData函数中的obj.logo = arr[0].channels.logo;行。

Logs

1 个答案:

答案 0 :(得分:0)

此代码的问题在于以下部分:

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;
};

ajax调用是异步的,但它被视为同步。这就是为什么它将返回{}的结果,因为success函数执行得晚。如果您尝试在console.log内添加success功能,您会看到它会显示在sortData.内的日志之后这就是为什么在您的日志中显示Array [{}, {}]都是空的。

解决此问题的一种方法是异步编码:

确保jsonpCall返回Promise。默认情况下,$.ajax()会返回Promise

在这部分代码中:

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

您必须使用.then回调异步处理它。

请看这个小提琴:https://jsfiddle.net/kLnsf1gn/2。我在其中添加了评论以便于理解。