Chrome ajax 302 问题

来源:互联网 发布:java设置时间格式 编辑:程序博客网 时间:2024/05/09 03:17

ECSHOP的后台每次删除一个商品都要报下面的错误

Uncaught transport.js/parseResult() error: can't parse to JSON.

错误的原因是ajax的返回值是空字符串, 而ajax中规定的格式是JSON, 返回之后要对字符串进行parseJSON, 空字符串被认为不是合法的JSON字符串. 看看代码就知道了:

            try {                if (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(this)) {                    var eval('(' this ')');                    if (typeof filter === 'function') {                        function walk(kv) {                            if (&& typeof === 'object') {                                for (var in v) {                                    if (v.hasOwnProperty(i)) {                                        v[i] = walk(iv[i]);                                    }                                }                            }                            return filter(kv);                        }                        walk(''j);                    }                    return j;                }            catch (e) {            // Fall through if the regexp test fails.            }            throw new SyntaxError("parseJSON");        };

正则表达式会是false, 从而抛出异常. 这里主要的原因是为什么AJAX返回空字符串. 比如一个典型的ajax url:

"http://127.0.0.144/shop/admin/goods.php?is_ajax=1&act=remove&id=32&cat_id=0&intro_type=&is_promote=0&stock_warning=0&brand_id=0&keyword=&suppliers_id=&is_on_sale=&sort_by=goods_id&sort_order=DESC&extension_code=&is_delete=0&real_goods=1&record_count=1&page_size=15&page=1&page_count=1&start=0&1346143445423423"

这个url会执行一个删除商品的动作然后执行一个header location进行重定向, 重定向的url会返回刷新的商品列表的JSON表示, 返回到ajax中, 解析之后写入到HTML页面上. 这原本是一个普通的ajax删除然后刷新, 而且在IE下面工作很正常. 而Chrome里面行不通. 搜索了一下, 这可能是一个问题, 不知道算不算bug, 在Chrome 18里面就提出来了, 例如http://code.google.com/p/chromium/issues/detail?id=121614 , 我用的是19, 显然问题还是没有修复.

先讲一下原理, header Location会发送一个302的HTTP响应, 按照WEB标准, 浏览器应该透明的执行重定向, 应用程序应该可以对重定向的过程毫不知情, 也不应该收到302这个状态, 例如请求a.php, 但是得到的是b.php的输出, 如果b.php正常执行那么ajax应该直接得到一个200的响应. 那么Chrome是如何处理这个问题的? 在控制台中打开Network面板得到下面的图:

Chrome收到了302, 但是每一个302都是canceled. 显然这是浏览器内部的行为, 与脚本无关. 然后我用了jQuery来测试了一下

a.php<script>$(document).ready(function(){  $('#abutton').click(function(){        $.ajax({        type: 'GET',        url: 'b.php',        data: {            usertheme : 'sss'        },        dataType: 'text',                success : function(xml) {            var a = 'jjiji';alert('success' + xml);        },        error : function(a,b,c) {            var b = 'sjfiwf'; alert('error');        },        complete : function() {            alert('complete');        }    });          });});</script><body><a href="javascript:;" id="abutton">ajax请求</a></body>b.php<?php//echo 'ajfeiofjei;'; exit;header("Location: c.php"); exit;?>c.php<?phpecho 'output form c.hphp'exit;?>

结果$.ajax的error函数被调用.

Chrome的控制台有个"Copy as HAR"的功能, 是请求响应的详细信息, 从中可以发现一点蛛丝马迹:

        "request": {          "method""GET",          "url""http://127.0.0.144/shop/admin/goods.php?is_ajax=1&act=remove&id=32&cat_id=0&intro_type=&is_promote=0&stock_warning=0&brand_id=0&keyword=&suppliers_id=&is_on_sale=&sort_by=goods_id&sort_order=DESC&extension_code=&is_delete=0&real_goods=1&record_count=1&page_size=15&page=1&page_count=1&start=0&1346143445423423",          "httpVersion""HTTP/1.1",          "headers": [            {              "name""Accept-Encoding",              "value""gzip,deflate,sdch"            },            {              "name""Accept-Language",              "value""zh-CN,zh;q=0.8"            },                         ],          "cookies": [            {              "name""ECS_LastCheckOrder",              "value""Tue%2C%2028%20Aug%202012%2008%3A43%3A40%20GMT",              "expires"null,              "httpOnly"false,              "secure"false            },                   ],          "headersSize"2775,          "bodySize"0        },             "response": {          "status"302,          "statusText""Found",          "httpVersion""HTTP/1.1",          "headers": [                     {              "name""Server",              "value""Apache/2.0.63 (Win32) PHP/5.2.10"            },            {              "name""Location",              "value""goods.php?act=query&is_ajax=1&&id=32&cat_id=0&intro_type=&is_promote=0&stock_warning=0&brand_id=0&keyword=&suppliers_id=&is_on_sale=&sort_by=goods_id&sort_order=DESC&extension_code=&is_delete=0&real_goods=1&record_count=1&page_size=15&page=1&page_count=1&start=0&1346143445423423"            },                   ],          "cookies": [],          "content": {            "size"0,            "mimeType""text/html",            "compression"0          },          "redirectURL""goods.php?act=query&is_ajax=1&&id=32&cat_id=0&intro_type=&is_promote=0&stock_warning=0&brand_id=0&keyword=&suppliers_id=&is_on_sale=&sort_by=goods_id&sort_order=DESC&extension_code=&is_delete=0&real_goods=1&record_count=1&page_size=15&page=1&page_count=1&start=0&1346143445423423",          "headersSize"712,          "bodySize"0        },        "cache": {},                "pageref""page_12"      },            {        "request": {          "method""GET",          "url""http://127.0.0.144/shop/admin/goods.php?act=query&is_ajax=1&&id=32&cat_id=0&intro_type=&is_promote=0&stock_warning=0&brand_id=0&keyword=&suppliers_id=&is_on_sale=&sort_by=goods_id&sort_order=DESC&extension_code=&is_delete=0&real_goods=1&record_count=1&page_size=15&page=1&page_count=1&start=0&1346143445423423",          "httpVersion""HTTP/1.1",          "headers": [            {              "name""User-Agent",              "value""Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.1 Safari/536.5"            },            {              "name""Referer",              "value""http://127.0.0.144/shop/admin/goods.php?act=list"            }          ],            ],          "cookies": [],          "headersSize"495,          "bodySize"0        },        "response": {          "status"0,          "statusText""",          "httpVersion""HTTP/1.1",          "headers": [],          "cookies": [],          "content": {            "size"0,            "compression"0          },          "redirectURL""",          "headersSize"13,          "bodySize"0        },

里面记录了请求响应的流程, 这里面第一个url请求, 响应是一个302, 之后根据302响应头中的Location字段构造了一个重定向的请求, 得到一个状态值为0的响应, 这个响应就是在ajax返回的时候所看到的那个, 符合透明重定向的原则. 看起来似乎有一个GET请求是指向重定向的url的, 而且还有一个response, 这个response的状态值是0. 那么这个GET请求到底有没有发出去, 答案是没有. Chrome只是构造了这个请求, 然后因为某种原因canceled, 之后又构造了一个response, 一个没有任何内容的response, 返回给ajax.

仍然没有搞清楚的是Chrome根据什么条件决定cancel这个重定向请求 ?

有一点要提到的是, 有些帖子里面说判断status的值, 如果是302就获取其header中的Location, 然后赋值给document.location. 这是行不通的, 因为302状态码是不会在脚本中见到的, 脚本要么得到一个错误或者200或者状态0 . StackOverflow上面有好多这样的例子, 容易误解.

0 0
原创粉丝点击