zoukankan      html  css  js  c++  java
  • jsonp的理解

    众所周知:在开发过程中,有时候需要客户端从服务器接收或向服务器发送一些数据;如果使用普通的ajax,则会遇到跨域访问无权限的问题。

    要解决这个问题,就需要了解一下jsonp了:

    1. ajax请求普通文件存在跨域访问无权限的问题。
    2. 但是当远程请求js文件时则不受跨域影响,而且只要是有src属性的标签都有跨域的能力
    3. 如果想通过纯web端跨域访问数据就只有一种可能,就是在服务端设法把数据封装进js文件中,给客户端
    4. 刚好json的数据格式是被js支持的

    有了以上4点,解决方案就呼之欲出了,先来个简单的例子(django):

    首先创建一个api.js:

    alert('我在服务器上!')

    然后在index页面上加载js:

    {% load staticfiles %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页</title>
    </head>
    <body>
        <h1>我是主页</h1>
    
        <script src="{% static 'jsnpapp/api.js' %}"></script>
    </body>
    </html>

    接下来启动服务器访问一下:

    image

    这样似乎没有什么意义,它们在同一个域中! 那现在我们在本地桌面上新建立一个index.html文件来模拟跨域:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页</title>
    </head>
    <body>
        <h1>我是主页</h1>
    
        <script src="http://localhost:8000/static/jsnpapp/api.js"></script>
    </body>
    </html>

    可以看到,在本地的index.html中调用了远程服务器的api.js文件;下面用浏览器打开本地index.html:

    image

    可以看到远程服务器的js被本地执行了。

    现在改进一下:

    在本地index.html中定义一个函数:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页</title>
    </head>
    <body>
        <h1>我是主页</h1>
    
        <script>
        var localHandler = function(data) {
            alert('我是本地的函数,我要跨域调用,远程js带来的数据是:'+data.result);
        }
        </script>
        <script src="http://localhost:8000/static/jsnpapp/api.js"></script>
    </body>
    </html>

    服务器上的api.js也修改一下:

    localHandler({"result":"我是远程js带来的数据"});

    有点意思,远程服务器要执行本地的函数;我们用浏览器打开本地index.html看看效果:

    image

    很完美,本地的函数被远程服务器跨域执行了,而且本地也得到了服务器发来的数据。这样一个跨域就实现了。 但问题是,这些数据都是写死的,

    怎么让远程服务器端知道本地的函数名呢,然后返回不同的数据呢?毕竟服务端是要服务很多客户的,这些客户的需求是不一样的。

    如果客户端能传递一个参数给服务器,告诉服务器“我要XX函数的数据,请返回给我”, 于是服务端就可以按照客户端的请求响应数据了。

    再改进一下,动态响应客户端

    先修改一下本地的Index.html,   为了满足各种需求,那么请求url的参数就不能被写死,要动态生成;可以使用动态生成<script>标签的方法来实现:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页</title>
    </head>
    <body>
        <h1>我是主页</h1>
    
        <script>
            var localHandler = function(data) {
                alert('我是本地的函数,我要跨域调用,远程js带来的数据是:'+data.result);
            }
            
             // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
             var url = "http://localhost:8000/jsnpapp/api?code=1&callback=localHandler";
             // 创建script标签,设置其属性
             var script = document.createElement('script');
             script.setAttribute('src', url);
             // 把script标签加入head,此时调用开始
             document.getElementsByTagName('head')[0].appendChild(script);
             
             
        </script>
    </body>
    </html>

    服务端,首先要创建一个url, 然后views, 服务端接收到客户端发来的参数后,动态生成了localHandler这个函数的javascript代码并返回给客户端:

    urlpatterns = [
        url(r'^api/', views.base_api),
        url(r'^index/$', views.index),
    
    ]
    def base_api(request):
        if request.method == "GET":
            code = request.GET.get('code')
            callback = request.GET.get('callback')
            if code == '1':
                msg = "%s({'result':'你给我1, 我就给你1111'})" % callback
                print('msg:', msg)
                return HttpResponse(msg)
        return HttpResponse('我是服务器!')

    浏览器运行index.html :

    image

    客户端成功获取到了服务端返回的数据。jsonp的执行过程全部完成。

  • 相关阅读:
    如何实现Android重启应用程序代码 ?
    Android Intent.FLAG_NEW_TASK详解,包括其他的标记的一些解释
    WebView 和Animation冲突
    CopyOnWriteArrayList与Collections.synchronizedList的性能对比
    混淆后显示行号
    java 多线程操作List,已经做了同步synchronized,还会有ConcurrentModificationException,知道为什么吗?
    【2015年最新App Store退款流程详解】最详细AppStore退款流程图文教程
    Android 编程下 Touch 事件的分发和消费机制
    Android TouchEvent事件传递机制
    svn 规范apk的生成命名
  • 原文地址:https://www.cnblogs.com/huangxm/p/5931499.html
Copyright © 2011-2022 走看看