• 使用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也方便很多。

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

  • 相关阅读:
    485串口接线
    mvc3 升级mvc5
    VB连接ACCESS数据库,使用 LIKE 通配符问题
    VB6 读写西门子PLC
    可用的 .net core 支持 RSA 私钥加密工具类
    解决 Win7 远程桌面 已停止工作的问题
    解决 WinForm 重写 CreateParams 隐藏窗口以后的显示问题
    解决安装 .net framework 发生 extracting files error 问题
    CentOS7 安装配置笔记
    通过特殊处理 Resize 事件解决 WinForm 加载时闪烁问题的一个方法
  • 原文地址:https://www.cnblogs.com/wujilong/p/3066174.html
Copyright © 2020-2023  润新知