• rails与jsonp


    涉及后台的东西,我也不敢保证对错,总之写出来如果有错望各位高人不吝赐教吧。跨域的需要大多数出于web2.0的mashup,如果我的网站想搞一个地图,但自己实现没有钱没有技术显然难度太大,这样可以利用google map,又如想加入天气预报,这样也可以调用yahoo网站提供的相关服务。这些服务常常是一些HTTP GET形式的API。那么我们就发起一个get请求就是,往往可以得到一段文本或xml,然后我们就可以搞鼓了……本文提到的jsonp,或许说动态JS标签更合适些,与上面提到的情形有些不同。上面的google,yahoo都不属性于你的东西,你只要传入URI外加几个参数,它就会返回一堆东西,然后你再用它们提供的代码加工一下。如本博客引用feedsky的服务,就是这种情况。由于这情况太简单,不在本文讨论范围内。我所说的情况是有两个网站,它们都是我们开发的。我们从一个网站发送请求,另一个网站接收请来,返回数据,交由原网站处理。发送的请求当然是get请求,就是普通动态加载JS文件,不过这JS文件是另一个网站生成的。看一下面代码:

    <!doctype html>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Demo by 司徒正美</title>
        <script type="text/javascript">
          //在原页设置函数体
          function say(words) {
            alert(words);
          }
        </script>
      </head>
      <body>
        <!--在远程js文件上调用本地函数//-->
        <script src="http://yabooo.org/remote.js" type="text/javascript"></script>
    
      </body>
    </html>
    

    JS文件很简单:

    say("司徒正美!")
    

    弹出司徒正美

    一般认为这就是JSONP的原型,用一个以js文件作结尾的URL请求另一个域的服务器,然后让它把所需要的东西全部搞成一个JSON对象,作为本地函数的参数传入执行。下面的例子需要rails支持,有兴趣的可以看看。

    设置控制器:

    class FooController < ApplicationController
      def bar
        respond_to do |format|
          format.html
          format.js do  
            render :update do |page|
              page << %{
              say("司徒正美!")
              }
            end
          end
        end
      end
    end
    

    设置layout:

    #D:\demo\views\layouts
    <!doctype html>
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Demo</title>
      </head>
      <body>
          <h1>layout</h1>
          <%= yield %>
      </body>
    </html>
    

    设置视图:

    #D:\polyline\app\views\foo\bar.html.erb
    <script type="text/javascript">
      //在原页设置函数体
      function say(words) {
        alert(words);
      }
    </script>
    <!--在远程js文件上调用本地函数//-->
    <%= javascript_include_tag "/foo/bar.js"  %>
    

    设置路由规则:

     map.resources :foo, :collection => { :bar => :get}
    

    然后打开http://localhost:3000/foo/bar.html,就会看到alert了,证明调用成功。

    下面是一个增强版,由于可怜的我没有网站与域名,姑且用另一个action冒充第二个网站吧,反正我们都知道JS文件是不受域名限制的,很完美地绕过所谓的同源策略。

    class FooController < ApplicationController
     
      def bar
    
      end
      def laaa
        respond_to do |format|
          format.html
          format.js do
            render :update do |page|
              page << %{
              say(" laaa")
              }
            end
          end
        end
      end
    end
    
       map.resources :foo, :collection => { :bar => :get,:laaa => :get}
    
    <script type="text/javascript">
      //在原页设置函数体
      function say(words) {
        alert(words);
      }
    
      var url = "http://localhost:3000/foo/laaa.js"; // URL of the external script
      // this shows dynamic script insertion
      var script = document.createElement('script');
      script.setAttribute('src', url+"?"+(+new Date));
      script.setAttribute("charset", "utf-8");
      // load the script
      document.getElementsByTagName('head')[0].appendChild(script);
    </script>
    

    再修改一下,这次传入json做参数。rails在这方面做得很好,可以直接把从数据库取得的记录用to_json转换成JSON,不过我现在不需要这么复杂。

    class FooController < ApplicationController
    
      def bar
      
      end
      def laaa
    
    
        respond_to do |format|
          format.html
          format.js do
            if params[:jsonp].present?
              callback = params[:jsonp]
              render :update do |page|
                page << %{
              #{callback}({"a":"司徒正美","b":"RestlessDream"})
                }
              end
            end
          end
        end
      end
    end
    
    <script type="text/javascript">
      //在原页设置函数体
      function say(json) {
        alert(json.a+" : "+json.b);
      }
    
      function jsonp(url,callback){
        if (url.indexOf("?") > -1)
          url += "&jsonp="+callback
        else
          url += "?jsonp="+callback
        url += "&nocache=" +(+new Date()); // prevent caching
    
        var script = document.createElement("script");
        script.setAttribute("src",url);
        script.setAttribute("type","text/javascript");
        script.setAttribute("charset", "utf-8");
        document.getElementsByTagName('head')[0].appendChild(script);
      }
    
      jsonp("http://localhost:3000/foo/laaa.js","say")
    
     
    </script>
    

    这次会弹出司徒正美 : RestlessDream,当然现实的需要会很复杂,会对传回来的JSON进行深加工,很少会像这样对号入座。不过处理JSON总比处理XML好。有时可能加载N多JSON,那么后台就要设置更多的分支,前台动态生成的script标签也随之增加,那么我们加载完这些标签后,可以立即删除,这是没有问题的。

    好了,这样就完了,更复杂更完善的东西结合Ajax再说吧。

  • 相关阅读:
    序例化-Externalizable 接口
    线程休眠
    线程优先级
    const & 用法
    AcGePoint3d ads_point 转换
    结果缓冲区 resbuf具体用法
    选择集用法
    引用用法
    通过用户选择获取各种东西
    ARX中类型强制转换
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1638779.html
Copyright © 2020-2023  润新知