jQuery AJAX JSONP 错误 "Unexpected token"

4

我正在尝试在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

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

(关于IT技术)

2
对于JSONP,您需要一个函数包装器。简单的JSON对象不是有效的JSONP响应。服务器是否实际能够提供JSONP响应? - Christoph
另外,dataType: 'jsonp',jsonp: false 看起来不正确。 - Christoph
1
@Christoph Re dataType: 'jsonp', jsonp: false 这是正确的,可以查看 http://api.jquery.com/jQuery.ajax/ 上的文档。 - Eric
1
иҜ»иҖ…иҝӣдёҖжӯҘи§ЈйҮҠпјҡ JSONеӨҙжҳҜcontent-type:application/json JSONPеӨҙеә”иҜҘеғҸиҝҷж ·Content-Type:application/javascript - Eric
一个简单的JSON请求应该可以在这里工作。移除jsonp内容并将数据类型改为json。 - Christoph
显示剩余5条评论
3个回答

3
经过仔细测试发现,由于跨域限制,当ajax期望返回JSONP时,无法捕获JSON对象结果。尽管响应状态=200。
我一直在使用jQuery AJAX调用进行测试,希望能够捕获结果,尽管浏览器会抛出解析错误,但似乎不可能。看起来响应文本在JS工作完成后才到达头部。
正如@Florian F. @Likwid_T @Christoph上面建议的那样,需要一个服务器端脚本才能使其正常工作。其他开发人员似乎喜欢使用C#编写的代理作为解决方案。

1

JSONP 不是开箱即用的。

JSONP 通过在 script 标签中加载结果来绕过跨域限制。

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

在发送响应之前,在服务器端执行所需操作:

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

PHP 代码示例:

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

它将使用正确的参数执行您的“done”匿名函数。(JQuery处理其他所有内容)

你为什么认为他能修改服务器?如果他正在进行跨域请求,很可能他并不能控制这个。 - Christoph
因为这是唯一的解决方案。跨域只有在您控制服务器或服务器本身接受时才有用。下一个解决方案是在您自己的域上构建代理,将请求转发到Web服务。 - Florian F.
@FlorianF。Christoph是对的,我无法控制服务器。我的项目仅限于JS。 - Eric
@FlorianF。如果能作为独立程序运行,那会更方便,但不幸的是,这段代码必须作为扩展运行。它全部都是JS。 - Eric
@Eric 那就没有解决方案了。或者是我不知道的。 - Florian F.
显示剩余2条评论

1

Christoph是正确的,你需要将你的答案包含在回调函数中,在你的情况下,在PHP文件的末尾:

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

或者如果您需要一个更复杂的对象。
echo $_GET['receive'] . '(' . json_encode(array(name1 => object1, name2 => object2, name3 => object3)) . ');';

您可能需要进行一些微调,但基本上每当我得到意外的标记时,几乎总是语法错误导致jQuery无法获取我的回调函数。


他没有控制服务器端的权限,我认为。否则,在大多数情况下,您不必执行跨域请求。 - Christoph
@Likwid_T 不幸的是,不能涉及任何服务器端脚本。它必须保持JS。 是否可以在JS中应用相同的操作? 尽管我可以在响应头中看到返回的JSON对象结果,但我的回调函数没有接收到数据。 - Eric
等等,我重新读了一遍:你是从响应中获取服务器上的数据吗?{"permalink": "https://www.virustotal.com/url/b5b546fdbb49a2258e951c5e568a52655c65ac56112e39d15af0954a53b36772...等等?这样正确吗? - Thierry Blais
如果你使用console.log(data["permalink"]);会发生什么? - Thierry Blais

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接