【问题标题】:jQuery AJAX JSONP error "Unexpected token"jQuery AJAX JSONP 错误“意外令牌”
【发布时间】:2013-01-28 23:34:30
【问题描述】:

我正在尝试在 Chrome 中进行跨域 JSONP 调用,但我不断返回 "Uncaught SyntaxError: Unexpected token :" 我已经尝试过:更改响应内容类型、设置 xhr 标头、JSON.stringify,以及此处提供的大多数解决方案,但到目前为止没有任何效果:-(

 $.ajax({
                type: "POST",
                url: "https://www.virustotal.com/vtapi/v2/url/report",
                crossDomain: true,
                contentType: "application/json; charset=UTF-8",
                dataType: 'jsonp',
                data: {
                    apikey: "*",
                    resource: "http://www.1001freefonts.com/font/BaroqueScript.zip"
                },
                jsonp: false,
                jsonpCallback: receive,
                success: function (data, textStatus, jqXHR) {
                    console.log("Data retrieved: " + data);
                }
            }).done(function () {
                console.log('I think we are done here');
            })
        .error(function (e) {
            console.log(arguments);
            console.log('something went funny here');
        })
        .complete(function (xhr, status) {

            console.log("complete");
        if (status === 'error' || !xhr.responseText) {
            console.log('error');
        }
        else {
            console.log("data found:" + xhr.responseText);
            //...
        }
    });
    });

    function receive(saveData) {
        if (saveData == null) {
            console.log("DATA IS UNDEFINED!");  // displays every time
        }
        console.log("Success is " + saveData);  // 'Success is undefined'
    }

在调试器中我可以看到响应

{"permalink": "https://www.virustotal.com/url/b5b546fdbb49a2258e951c5e568a52655c65ac56112e39d15af0954a53b36772/analysis/1360339512/", "url": "http://www.1001freefonts.com/font/BaroqueScript.zip", "response_code": 1, "scan_date": "2013-02-08 16:05:12", "scan_id": "b5b546fdbb49a2258e951c5e568a52655c65ac56112e39d15af0954a53b36772-1360339512", "verbose_msg": "Scan finished, scan information embedded in this object", "filescan_id": "b7e13c0242e9690aba1f3da4b73d9c2e99a9b7fd03f542b55e694a34aaf9eca8-1360339519", "positives": 0, "total": 35, "scans": {"CLEAN MX": {"detected": false, "result": "clean site"}, "MalwarePatrol": {"detected": false, "result": "clean site"}, "ZDB Zeus": {"detected": false, "result": "clean site"}, "K7AntiVirus": {"detected": false, "result": "clean site"}, "Quttera": {"detected": false, "result": "clean site"}, "Yandex Safebrowsing": {"detected": false, "result": "clean site"}, "MalwareDomainList": {"detected": false, "result": "clean site"}, "ZeusTracker": {"detected": false, "result": "clean site"}, "zvelo": {"detected": false, "result": "clean site"}, "Google Safebrowsing": {"detected": false, "result": "clean site"}, "BitDefender": {"detected": false, "result": "clean site"}, "Opera": {"detected": false, "result": "clean site"}, "G-Data": {"detected": false, "result": "clean site"}, "C-SIRT": {"detected": false, "result": "clean site"}, "Sucuri SiteCheck": {"detected": false, "result": "clean site"}, "VX Vault": {"detected": false, "result": "clean site"}, "ADMINUSLabs": {"detected": false, "result": "clean site"}, "SCUMWARE.org": {"detected": false, "result": "clean site"}, "Dr.Web": {"detected": false, "result": "clean site"}, "AlienVault": {"detected": false, "result": "clean site"}, "Malc0de Database": {"detected": false, "result": "clean site"}, "SpyEyeTracker": {"detected": false, "result": "clean site"}, "Phishtank": {"detected": false, "result": "clean site"}, "Avira": {"detected": false, "result": "clean site"}, "Antiy-AVL": {"detected": false, "result": "clean site"}, "Comodo Site Inspector": {"detected": false, "result": "clean site"}, "Malekal": {"detected": false, "result": "clean site"}, "ESET": {"detected": false, "result": "clean site"}, "SecureBrain": {"detected": false, "result": "unrated site"}, "Netcraft": {"detected": false, "result": "clean site"}, "ParetoLogic": {"detected": false, "result": "clean site"}, "URLQuery": {"detected": false, "result": "unrated site"}, "Wepawet": {"detected": false, "result": "unrated site"}, "Minotaur": {"detected": false, "result": "clean site"}}}

我已经在 http://jsonlint.com/ 上验证了它,它表明它是一个有效的 JSON。

这里是响应标头

cache-control:no-cache
content-encoding:gzip
content-length:695
content-type:application/json
date:Wed, 13 Feb 2013 12:00:33 GMT
server:Google Frontend
status:200 OK
vary:Accept-Encoding
version:HTTP/1.1

有人有什么想法/建议吗?

【问题讨论】:

  • 对于 JSONP,您需要一个函数包装器。普通 JSON 对象不是有效的 JSONP 响应。服务器真的能够提供 JSONP 响应吗?
  • 另外dataType: 'jsonp', jsonp: false 看起来不正确。
  • @Christoph Re dataType: 'jsonp', jsonp: false 他们是正确的,请查看api.jquery.com/jQuery.ajax 的文档
  • @Christoph 在进一步检查后似乎服务器只能发回 JSON 而不能发回 JSONP。我需要弄清楚如何转换响应。
  • 对读者JSON头的进一步解释是content-type:application/json JSONP头应该是这样的Content-Type:application/javascript

标签: javascript jquery ajax xmlhttprequest jsonp


【解决方案1】:

经过全面测试,很明显,当 ajax 期望 JSONP 作为回报时(由于跨域限制),无法捕获 JSON 对象结果。即使响应状态 = 200。

我一直在使用 jQuery AJAX 调用进行测试,试图查看是否仍然可以捕获结果——尽管浏览器抛出了解析错误——但这似乎是不可能的。看起来响应文本是在 JS 工作完成后到达头部的。

正如@Florian F. @Likwid_T @Christoph 上面所建议的,服务器端脚本绝对需要使其正常工作。其他开发人员似乎热衷于使用用 C# 编写的代理作为解决方案。

【讨论】:

    【解决方案2】:

    JSONP 不能开箱即用。

    JSONP 通过将结果加载到脚本标签中来绕过跨域限制。

    基本上,您的服务器必须启用 JSONP。

    在发送响应之前,在服务器端做任何需要做的事情:

    1. 检查请求是否设置了“_callback”
    2. 如果设置,则使用 _callback 的值包装您的内容。
    3. 发送您的数据

    PHP 中的代码示例:

    $responseString = '{"smthing":"val","smthingelse":"val2"}';
    if (isset($_REQUEST['_callback'])) {
        $responseString = $_REQUEST['_callback'] . '(' . $responseString . ');';
    }
    

    它将使用正确的参数执行您的“完成”匿名函数。 (JQuery 处理一切)

    【讨论】:

    • 什么让你觉得,他可以修改服务器?如果他正在执行跨域请求,很可能他没有控制这一点。
    • 因为它是唯一的解决方案。跨域仅在您控制服务器或服务器自己接受时才有用。下一个解决方案是在您自己的域上构建一个代理,将请求转发到网络服务。
    • @FlorianF。 Christoph 是对的,我无法控制服务器。我的项目仅限于 JS。
    • @Eric 那么你自己的服务器上的代理呢?
    • @FlorianF。它会让生活更轻松,不幸的是代码必须作为扩展运行。都是 JS。
    【解决方案3】:

    Christoph 是对的,您需要在回调函数中包含您的答案,在您的情况下位于 PHP 文件的末尾:

    echo $_GET['receive'] . '(' . json_encode($yourResultObject) . ');';
    

    或者如果您需要更复杂的对象

    echo $_GET['receive'] . '(' . json_encode(array(name1 => object1, name2 => object2, name3 => object3)) . ');';
    

    您可能需要稍作调整,但基本上每当我得到 Unexpected token 时,几乎总是一个语法错误,导致 jQuery 无法获取我的回调函数。

    【讨论】:

    • 我认为他无法控制服务器端。否则在大多数情况下,您不必执行跨域请求。
    • @Likwid_T 不幸的是,不能涉及服务器端脚本。它必须保持 JS。是否可以在 JS 中应用相同的操作?我的回调函数没有接收到数据,即使我可以在响应标头中看到返回的 JSON 对象结果。
    • 等一下,我刚刚重新阅读:您是从响应中的服务器获取数据吗? {"permalink": "virustotal.com/url/…... 等等?对吗?
    • 如果你使用 console.log(data["permalink"]); 会发生什么
    猜你喜欢
    • 1970-01-01
    • 2012-10-07
    • 2012-11-24
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 2011-11-09
    相关资源
    最近更新 更多