回调函数“未定义”

时间:2012-01-31 21:25:21

标签: javascript json callback jsonp tumblr

我正在构建一个脚本,从Tumblr获取多个JSON源,并根据该数据创建HTML列表。相当简单的概念。

这是输出:http://fotis.co/tumblr/index.html

脚本部分工作,因为我在“回调函数未定义”问题上遇到了绊脚石。只有当我在请求Tumblr JSON提要时选择使用回调函数时才会发生这种情况。默认情况下,如果未通过Tumblr API指定回调函数,则返回的JSON对象将分配给名为tumblr_api_read的变量。所以JSON实际上会返回:

var tumblr_api_read = {the JSON object data goes here};

如果我使用回调函数,则返回JSON数据(如预期的那样):

callbackFunctionName({the JSON object data goes here});

如果您在此处查看脚本代码http://fotis.co/tumblr/tumblr.js

/* Read Tumblr */

function ready(cb) {
    /in/.test(document.readyState) ? setTimeout('ready('+cb+')', 9) : cb();
}

function getTumblrFeed(params) {
    /*
    Legend:
    start - The post offset to start from. The default is 0.
    num - The number of posts to return. The default is 20, and the maximum is 50.
    type - The type of posts to return. If unspecified or empty, all types of posts are returned. Must be one of text, quote, photo, link, chat, video, or audio.
    id - A specific post ID to return. Use instead of start, num, or type.
    filter - Alternate filter to run on the text content. Allowed values:
        text - Plain text only. No HTML.
        none - No post-processing. Output exactly what the author entered. (Note: Some authors write in Markdown, which will not be converted to HTML when this option is used.)
    tagged - Return posts with this tag in reverse-chronological order (newest first). Optionally specify chrono=1 to sort in chronological order (oldest first).
    search - Search for posts with this query.
    */
    if(params.blogurl) var blogurl = params.blogurl;
    if(params.postcount) var num = params.postcount;
    var jsonurl = document.location.protocol+ '//' +blogurl+ '/api/read/json?num=' +num;
    if(params.type) jsonurl += '&type=' + params.type;
    if(params.tagged) jsonurl += '&tagged=' + params.tagged;
    if(params.search) jsonurl += '&search=' + params.search;
    if(params.callback) jsonurl += '&callback=' + params.callback;
    var jsonfeedscript = document.createElement('script');
    jsonfeedscript.setAttribute('charset', 'utf-8');
    jsonfeedscript.setAttribute('type', 'text/javascript');
    jsonfeedscript.setAttribute('async', 'true');
    jsonfeedscript.setAttribute('src', jsonurl);
    return jsonfeedscript;
}

function renderResults(settings) {
    var tumblrObj = (settings.callback) ? settings.callback : tumblr_api_read;

    var i = 0;
    var c = document.getElementById(settings.container);

    for(i; i<tumblrObj.posts.length; i++){
        // URL
        var postUrl = tumblrObj.posts[i]['url-with-slug'];
        // Title
        if(tumblrObj.posts[i]['regular-title']){
            var postTitle = tumblrObj.posts[i]['regular-title'];
        } else if(tumblrObj.posts[i]['quote-text']){
            var postTitle = tumblrObj.posts[i]['quote-text'];
        } else if(tumblrObj.posts[i]['link-text']){
            var postTitle = tumblrObj.posts[i]['link-text'];
        } else if(tumblrObj.posts[i]['audio-caption']){
            var postTitle = tumblrObj.posts[i]['audio-caption'];
        } else if(tumblrObj.posts[i]['photo-caption']){
            var postTitle = tumblrObj.posts[i]['photo-caption'];
        } else if(tumblrObj.posts[i]['video-caption']){
            var postTitle = tumblrObj.posts[i]['video-caption'];
        } else if(tumblrObj.posts[i]['conversation-text']){
            var postTitle = tumblrObj.posts[i]['conversation-text'];
        } else {
            var postTitle = '';
        }
        // Date
        var postDate = tumblrObj.posts[i]['date']; // or: date-gmt, unix-timestamp
        // Type
        var postType = tumblrObj.posts[i]['type'];
        // Output
        var output = settings.theme.replace("{postUrl}",postUrl).replace("{postTitle}",postTitle).replace("{postDate}",postDate);
        c.innerHTML += output;
    }

    // Hide the loader
    var l = document.getElementById(settings.loader);
    c.removeChild(l);
}

function readTumblr(settings) {
    // Load JSON data
    var head = document.getElementsByTagName('head')[0];
    var jsonfeedscript = getTumblrFeed(settings);
    head.appendChild(jsonfeedscript);

    jsonfeedscript.onload = function(){
        renderResults(settings);
    }
}

你会看到我检查是否使用回调函数调用JSON提要(在readTumblr()内),否则我只使用默认对象“tumblr_api_read”。如果没有定义脚本初始化的回调函数(在index.html内),则正确呈现Tumblr JSON数据(请参阅html输出中的容器2和3)。如果我定义一个回调函数,我得到类似“未定义callbackFunctioName”然后渲染失败。

我在这里遗漏了什么吗?这是范围问题吗?如果是这样,我怎么能绕过它呢?

提前感谢您的任何答案。

编辑1 :更新了上面的脚本代码。

2 个答案:

答案 0 :(得分:0)

如果您提供JSONP API的回调,您将获得一个JavaScript代码段,该代码段将您提供的任何函数作为参数调用JSON数据。如你所说:

callbackFunctionName({the JSON object data goes here});

JSONP /回调系统都依赖于已经定义callbackFunctionName函数的你的代码,所以有一些东西需要调用。我们的想法是,您需要在该回调函数中使用需要处理Tumblr数据的代码。

如果您更喜欢使用var tumblr_api_read方式,请不要指定回调。

否则,您基本上希望将当前拥有的jsonfeedscript.onload移动到您定义为回调的任何函数。例如,如果您为Tumblr API提供了“myCallback”的“回调”参数,那么您的代码应该基本上看起来像:

function myCallback(tumblrObj) {
    // Your code that reads the JSON and inserts the HTML
}

您根本不需要自己致电myCallback 。您只需插入script标记即可发出JSONP请求,Tumblr API会返回一个调用myCallback并传入JSON数据的脚本。

答案 1 :(得分:0)

不应该这一行:

tumblrObj = (settings.callback) ? settings.callback : tumblr_api_read

是:

tumblrObj = (settings.callback) ? settings.callback() : tumblr_api_read

我不确定,这对我来说很奇怪。