有点背景故事,我正在使用Twitch(游戏流媒体服务)api从网站上的频道中提取关注者列表。为了绕过CORS规则我正在使用JSONP。就个人而言,我更喜欢使用vanilla javascript而不是库,所以我从https://cameronspear.com/blog/exactly-what-is-jsonp/上的优秀文章中学到了如何做到这一点。
下面是我简化的javascript(实际代码可能不是非常必要,但也许它有助于在之后澄清我的问题):
//Function to pull JSONP
function pullJSONP(url) {
var JSONPInstance = document.createElement('script');
JSONPInstance.src = url;
JSONPInstance.onload = function () {
this.remove();
};
var head = document.getElementsByTagName('head')[0];
head.insertBefore(JSONPInstance, null);
}
//End function to pull JSONP
function storeCurrentFollows(offset) //Function to wrap entire operation
{
function pullStartSessionFollows(JSONdata) //Callback from JSONP down below
{
function pushNameElements(followEntry) //Function to add names into array
{
allSessionFollows.push(followEntry.user.name);
}
JSONdata.follows.forEach(pushNameElements); //Iterate through followers
storeCurrentFollows(offset+100); //Rerun operation, incrementing offset by 100
};
if(offset > 300){ return }
else
{
//running JSONP function from above, passing in url and setting a callback
pullJSONP('https://api.twitch.tv/kraken/channels/' + channelName + '/follows?direction=desc&limit=100&offset=' + offset + '&callback=pullStartSessionFollows');
}
}
storeCurrentFollows(0);
所以我的问题是这样,每当我按照这个顺序运行这个操作时,它会在控制台中返回错误> Uncaught ReferenceError: pullStartSessionFollows is not defined
。除非我将pullStartSessionFollows
函数移动到全局范围内,否则它无法正常工作。我不明白为什么它认为它是未定义的,即使它是在我运行pullJSONP()函数之前实例化的。我不想移动它因为那时我必须将我的偏移传递给两个不同的函数以及一些其他问题。非常感谢任何帮助或见解。提前谢谢!
答案 0 :(得分:1)
作为JSONP回调调用的函数必须是全局的(或全局对象的属性)。在全局上下文中评估作为JSONP服务的响应主体返回的回调表达式。服务器返回的内容看起来像
pullStartSessionFollows({ ... });
您的功能是在其他功能中定义的,因此它不是全局的。
答案 1 :(得分:1)
除非我将pullStartSessionFollows函数移动到全局范围内,否则它无法正常工作。
正确,JSONP回调必须是全局函数。它是JSONP工作方式的固有内容。
我不明白为什么它认为它是未定义的,即使它是在我运行pullJSONP()函数之前实例化的。
因为它会在您执行此操作的函数(storeCurrentFollows
)内创建函数,而不是全局函数。但JSONP的工作方式要求函数是全局的。
通过将JSONP调用声明为全局变量,只有在存在JSONP调用时才能存在pullStartSessionFollows
函数:
var pullStartSessionFollows;
...然后分配到storeCurrentFollows
中的内容:
pullStartSessionFollows = function() { /* ... */ };
您还可以在回调完成后将其删除:
pullStartSessionFollows = undefined;
为什么 回调函数必须是全局的?因为JSONP的工作方式是向页面添加一个脚本元素,就像你在HTML中写的那样:
<script src="http://example.com/get?callback=pullStartSessionFollows"></script>
...然后响应如下:
pullStartSessionFollows({/*...JSON here...*/})
这要求它是一个全球性的功能。
答案 2 :(得分:0)
jsonp回调必须存在于全局javascript范围内,因为在请求完成时,无法确定回调函数的原始范围,这就是为什么它将在全局范围内执行,这是非常容易访问的从任何范围。