谈谈jQuery和跨域访问



随着产品的不断完善,应用需要部署到不同的服务器上,突然执行某一次请求的时候,浏览器不响应了,才意识到我们也需要跨域访问了。

上网搜索“crossdomain”能找到一大堆东西,可以水准大都很烂,东拼西凑,不知所云。有关跨域访问从原理到应用,写得最好的一篇文章是《Cross-domain communications with JSONP, Part 1: Combine JSONP andjQuery to quickly build powerful mashups》,花点时间读完它,就没什么疑惑了。

 

搬砖头翻译的事情不想干了,梳理几个我觉得重要的地方。

由于浏览器的自身策略,异步请求与页面来源不同域的站点,会引发安全性错误。 一般有三种方法突破这种限制:访问页面所在的站点进行代理;利用IFrame访问不同域的站点;剩下的就是现在主流JSONPJSON with Padding)。

JSONP绝对是个坑爹的名字,其本质就是利用了动态插入JavaScript的原理(DynamicJavaScript Insertion)。浏览器虽然阻止跨域的异步请求,但是在HTML Header中的<script><link>标签可以引用任何来源的文件,我们可以动态创建一个<script>的标签,将它的src设定为异步请求的服务器地址,这样就能跨域请求了。但是这种模式下,浏览器接管了该请求,并处理响应结果。对于浏览器而言,只是通过GET方法试图下载被请求地址的内容,并且认为这是一个js文件,使用JavaScript引擎去执行其中的代码。所以如果要获取响应的结果,那么就要在下载内容中动脑筋,首先响应结果应该被封装成为JSON形式,同时请求发起者还需要提供一个回调函数,供下载完毕后,以响应结果作为参数执行该回调函数。

结合整个过程,我对JSONP是这样理解的:使用JSON填充响应结果。jQuery中的ajax方法对JSONP有很好的支持,甚至无需特别声明,jQuery内部根据请求地址自动判断,如果是跨域的就启动JSONP,如果是本域就是常规的AJAX。但是正因为跨域请求的返回结果不是常规的JSON,所以不仅需要客户端有特殊的方法,服务端也需要对JSONP进行专门的支持:服务端需要知道下载完毕后的回调函数是什么,需要把执行回调函数的JavaScript语句写入到响应流中。

这种专门支持JSONP的服务端被称之为“JSONP Service”,网上能搜索的绝大多数文档,都是谈客户端该怎么调用,没有涉及服务端,所以费了好大的劲才找到门路。

 

下面用一个简单的例子展示跨域请求的过程。

服务端(ASP.NET MVC 3.0

    [HttpGet]
    public ActionResult UserPath(Guid id,String callback)
    {
        String userPath = CreateUserDir(id);
        String output = String.Format("{0}(\"{1}\");", callback, userPath);
        this.Response.Write(output);
        return new HttpStatusCodeResult(200);
    }

首先服务端应该支持HTTPGET方法访问,回调函数应该作为请求的参数之一(如上述示例中的callback),响应流就是符合JavaScript语法规范的字符串,其中必须包含对于回调函数的调用语句。这里的响应结果比较简单,就是一个字符串。

 

客户端(jQuery 1.9

    var url = "http://server2/Pronunciation/UserPath?id=" + studentID + "&callback=?";
    $.getJSON(url, null, function (result) {
        runtime.AddRecordRootPath(result);
    });

客户端可以用jQuery提供的任何AJAX相关的函数,getJSON足够简单,所以推荐一下。示例当中使用了一个匿名函数作为回调函数,所以“callback=?”,如果回调是一个定义好的函数,那么应该为“callback=<functionname>”。

 

方法有点绕,如果理解原理的,也很简单。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。