• 使用JSONP来取代AJAX进行跨域


    说到用JavaScript动态加载内容,一般都会想到AJAX。
    但AJAX所用的XML其实并非必须,还有其他类型的数据结构(例如JSON和HTML)也可以实现。
    而且AJAX有个很大的问题:由于JavaScript的安全限制,AJAX的跨域非常麻烦。
    但如果使用JSONP的话,问题就很容易搞定了。

    JSONP就是JSON with Padding的缩写,意思是JSON加上一些填充。
    那么究竟填充什么呢?这就要说下原理了。
    当使用script标签时,浏览器可以加载来自外域的JavaScript文件。而JSON本身就是一个JavaScript的对象,所以浏览器也可以直接加载它们。
    但单纯的加载毫无用处,因为JSON只是数据,我们还需要处理它。因此,假如用括号将JSON数据包围起来,然后传给一个JavaScript function,那这个function就能处理这个JSON数据了。
    因此从技术上来说,JSONP并不是数据,而是JavaScript代码,和JSON是2个稍有区别的东西。

    首先来看最简单的实现:
    客户端:

    <html>
     <head>
      <title>JSONP Test</title>
        <script>
            function test(text) {alert(text.hello);}
        </script>
        <script src="test.json"></script>
     </head>
     <body>
     </body>
    </html>

    服务器端(就是那个test.json)

    test({"hello": "hello world!"})

    在浏览器中打开这个页面,将会弹出一个对话框,内容是hello world!。

    事实上,我们的test.json文件就是个JavaScript文件,它调用test方法,并将其中的JSON数据({"hello": "hello world!"})作为参数。

    也就是说,JSONP就是一次函数调用而已,明白这点就好办了。
    不过动态加载当然不可能直接用script标签来做,但JavaScript是可以操作DOM的,所以我们只需要把script标签添加到DOM,就能实现动态加载了。

    当然,改写DOM是个很麻烦的过程,我们可以使用一些JavaScript库来实现,下面就给个jQuery和GAE的例子:
    客户端:

    <!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>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <meta name="author" content="keakon" /> 
      <title>JSONP Test</title>
        <script type="text/javascript" src="http://www.google.com/jsapi"></script>
        <script type="text/javascript">
            google.load("jquery", "1.3.1");
        </script>
     </head>
    
     <body>
     <script>
        $.getJSON("http://localhost:8080/?jsoncallback=?",
            function (json) {
                alert(json.text);
            }
        );
     </script>
     </body>
    </html>

    服务器端(本来是发在Google的论坛的,所以注释用的是英文,将就看吧):

    import wsgiref.handlers
    from google.appengine.ext import webapp
    
    class MainHandler(webapp.RequestHandler):
      def get(self):
    
        # Since browsers can't handle application/json as a text,
        # and actually, it's a JavaScript code, not JSON, while I request jsoncallback,
        # I use text/javascript to both display and process it.
        self.response.headers['Content-Type'] = 'text/javascript; charset=UTF-8'
    
        json = {"text": "Hello world!"} # the json data I want to output
        jsoncallback = self.request.get('jsoncallback') # the jsoncallback argument
    
        # if doesn't contain jsoncallback argument, simply output it
        # otherwise, it should output jsoncallback_argument(json data)
        # eg: hello({"text": "Hello world!"})
        output = '%s(%s)' % (jsoncallback, json) if jsoncallback else json
    
        self.response.out.write(output)
    
    def main():
      application = webapp.WSGIApplication([('/', MainHandler)])
      wsgiref.handlers.CGIHandler().run(application)
    
    if __name__ == '__main__':
      main()

    jQuery隐藏了很多实现,实际上它会自动判断jsoncallback=?,然后将?替换为一个随机生成的函数名(实际上就是我们的匿名函数),于是就形成了一次函数调用。

    注意jsoncallback不是必须的,只是jQuery需要它的名字类似callback
    而且大多数都遵循这个命名规则,所以JSONP也被叫作JSON with callbacks
    个人也比较喜欢后者,因为更加贴近其原理,而不是其表面现象(填充了函数名和括号的JSON)。
    当然,你可以更改这个函数名,但必须使用$.AJAX函数的jsonp参数来指定,$.getJSON函数是不提供这个参数的。

    还在为AJAX跨域苦恼的不妨试试JSONP吧,而且JSON本身比XML也方便很多。

    文章来自网络,个人收藏,如有冒犯敬请原谅!

  • 相关阅读:
    基于java容器注解---基于泛型的自动装配
    mininet+floodlight搭建sdn环境并创建简单topo
    Bean装配之@Autowired注解
    Linux常用命令
    Bean利用Resource接口获取资源的几种方式
    MYSQL分页优化查询
    MYSQL统计和识别重复值
    MYSQL统计和识别重复值
    MYSQL处理数据重复值
    MYSQL处理数据重复值
  • 原文地址:https://www.cnblogs.com/wujilong/p/3066174.html
Copyright © 2020-2023  润新知