• 乱想跨域


    《ArcGIS API for JavaScript 开发教程》也告一段落,虽然很多还不是很清楚,但是心得还是有一点,我愿意将我的心得跟大家分享,喜欢和大家交流。

    一个比较执着的技术男,一旦遇到了问题,他想的首先是解决这个问题,然后想的可能是为什么会遇到这样的问题,其次可能是解决此类问题能有几种方法,如果将这些都能理清,能说出个所以然来,我想这个技术男体会肯定颇深,我喜欢看这样的博文,尤其是一些关于什么什么的探究,或者运行机制,以至于本质,更厉害的博主直接就将一些底层的代码给剖出来,对于这样的博文或者博主,我只能望其项背,望洋兴叹。我也喜欢写类似的博文,因为这些是自己体会所得,但是资质平庸,我只能泛泛而谈,算不上什么上乘之作。

    话题要从跨域开始,我在写《ArcGIS API for JavaScript 开发教程》的时候,当向服务器发送XmlHttpRequest请求的时候,经常遇到这个错误,虽然我成不了什么能将问题剖根到底,或者一针见血的指出其缘由,但是我喜欢将这些记录下来,只希望在不断的碰壁中得到正确的解决之道。之所以有这个问题,原因很简单,浏览器只允许请求当前源(域名、协议、端口)的资源,当浏览器发现两个请求不在同一个域中的时候,就报错。浏览器这么规定,那我们也只能接受,还是那句话,改变不了的那就默默接受吧!

         浏览器没有错,因为浏览器出于安全考虑,是不允许JavaScript代码进行跨域操作。比如,liuyu.com站点中的Ajax只能访问liuyu.com站点下的资源,而不能跨域访问esrichina.com站点中的资源,这就是Ajax跨域问题。既然知道问题了,那么我们想的就是绕过跨域。

    代理是一个解决方法,代理也是我用的最多的。

    代理实际上起到了一个请求中转的作用,当A机器向C服务器请求的时候,A机器可以由B机器转发请求,然后A机器从代获取代理服务器B和C服务器的结果.代理也是一个Web服务器上运行的。常常使用动态网页(ASP.NET,PHP,JSP等)作为代理页面来作为这种中转请求的。上面这个关系应该一清二楚,毋庸置疑,代理在《ArcGIS API for JavaScript 开发教程》可以看到,这里就不多说了。

    为什么在开发的时候可以直接使用Esri官网的在线的API?

    页面在提交请求时,浏览器会进行Form身份验证(Form即为表单,每个页面都有一个Form标签),当向不同域获取数据时,浏览器认为这是不安全的,所以拒绝访问。   而标签script中的src请求远程服务数据时是不需要经过Form表单身份验证的,因为该标签并不包含在Form中,所以可以用此方法来请求不同域的数据。

     测试,建立一个新的js文件内容如下:

    function Add (a, b) {
    
        return a + b;
    
    }
    
     
    
    alert(Add(1,2));
    
     
    
     
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    
    <head>
    
        <title>跨域测试</title>
    
        <script src="CrossTest.js" type="text/javascript"></script>
    
       <!-- <script src="http://localhost/CrossTest.js" type="text/javascript"></script>-->
    
    </head>
    
    <body>
    
     
    
    </body>
    
    </html>
    

     我们将这个JS文件部署在服务器上,这样就跟调用Esri的在线API类似。

     

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    
    <head>
    
        <title>跨域测试</title>
    
        <script src="CrossTest.js" type="text/javascript"></script>
    
       </head>
    
    <body>
    
     
    
    </body>
    
    </html>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    
    <head>
    
        <title>跨域测试</title>
    
       
    
        <script src="http://localhost/CrossTest.js" type="text/javascript"></script>
    
    </head>
    
    <body>
    
     
    
    </body>
    
    </html>
    

    可以看到,这两个都可以得到正确的结果.说明了script标签不受跨域影响,基于这个,我们也可以创建script标签,动态的来进行处理,如下:

     

     function
    ScriptTag(src){
    
         var script = document.createElement('script');
    
             script.setAttribute("type","text/javascript");
    
             script.src = src;
    
             document.body.appendChild(script);
    
         }
    
         
    
         window.onload = function(){
    
             ScriptTag("http://localhost/CrossTest.js");
    
         }
    

     

    http://www.cnblogs.com/chopper/archive/2012/03/24/2403945.html

    JSONP,这个在使用esri.request的时候也常见。 

    JSONP是JSON with Padding的略称。它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)

    JSONP通过一个回调函数来实现跨域的,当构建http请求参数的时候,如下:JSONPTest.ashx?callback=callback&a=3&b=4,callback是在客户端的一个函数,当服务器处理结束后,将有客户端这个函数进行回调处理,我们可以看下,esri.request这个请求的结构。

    esri.request的结构大体如下:

      esri.request({

            url:“yoururl”,

            content:params,

            callbackParamName:"callback",

            load:function (result) {

            //省略

           

            },

            error:function (error) {

                      //省略

        });

    }

     这个的意思不言而喻,当执行成功的话去处理load对象的函数,失败的话去处理error对应的函数。

    我们可以自己去模拟这个过程,下面是服务器端代码:

    public class JSONPTest : IHttpHandler
    
        {
    
     
    
         
    
                public void ProcessRequest(HttpContext context)
    
                {
    
                    //获取回调函数名
    
                    string callback = context.Request.QueryString["callback"];
    
     
    
                      JavaScriptSerializer js = new JavaScriptSerializer();
    
     
    
                      string a= context.Request.QueryString["a"];
    
     
    
                      string b = context.Request.QueryString["b"];
    
                  
    
                    //json数据
    
                    StringBuilder Str= new StringBuilder();
    
                    context.Response.ContentType = "application/json";
    
     
    
                    js.Serialize(new { message = callback, result = Add(Convert.ToDouble(a), Convert.ToDouble(b)) }, Str);
    
                         context.Response.Write(callback+"("+Str+")");                  
                }
    
     
    
     
    
                public double Add(double a, double b)
    
                {
    
                    return a + b;
    
                }
    
                public bool IsReusable
    
                {
    
                    get
    
                    {
    
                        return false;
    
                    }
    
                }
    
            }
    
     
    

     客户端的代码,这里大家可以得到正确的值。

       
     function callback(data) {
             alert(data.result);
         }

     模拟是为了更好的了解,只在说明问题,当然你可能有更好的方法,现在很多框架都提供了JSONP这种方式,我们就没必要自己去折腾了。

  • 相关阅读:
    白话算法(6) 散列表(Hash Table)从理论到实用(中)
    白话算法(6) 散列表(Hash Table) 从理论到实用(下)
    基于无锁的C#并发队列实现
    邻接表建图的三种方式的时空比较(解析+图示)
    Windows内存管理(1)--分配内核内存 和 使用链表
    Windows内存管理(2)--Lookaside结构 和 运行时函数
    error C2443: operand size conflict
    CPUID 指令的使用
    Windows内核驱动开发入门学习资料
    重载内核全程分析笔记
  • 原文地址:https://www.cnblogs.com/zuiyirenjian/p/3027389.html
Copyright © 2020-2023  润新知