整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

一篇文章搞懂 Django 中的 AJAX

一篇文章搞懂 Django 中的 AJAX

JAX准备知识:JSON

什么是 JSON ?

  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言 *
  • JSON 具有自我描述性,更易理解
  • * JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。


    合格的json对象:

    ["one", "two", "three"]
    { "one": 1, "two": 2, "three": 3 }
    {"names": ["张三", "李四"] }
    [ { "name": "张三"}, {"name": "李四"} ] 

    不合格的json对象:

    { name: "张三", 'age': 32 }  // 属性名必须使用双引号
    [32, 64, 128, 0xFFF] // 不能使用十六进制值
    { "name": "张三", "age": undefined }  // 不能使用undefined
    { "name": "张三",
      "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
      "getName":  function() {return this.name;}  // 不能使用函数和日期对象
    }

    stringify与parse方法

    JavaScript中关于JSON对象和字符串转换的两个方法:

    JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象 

    JSON.parse('{"name":"run1"}');
    JSON.parse('{name:"run1"}') ;   // 错误
    JSON.parse('[18,undefined]') ;   // 错误

    JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。 

    JSON.stringify({"name":"run1"})

    和XML的比较

    JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。

    JSON 格式有两个显著的优点:书写简单,一目了然;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。

    XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。

    用XML表示中国部分省市数据如下:

    <?xml version="1.0" encoding="utf-8"?>
    <country>
        <name>中国</name>
        <province>
            <name>黑龙江</name>
            <cities>
                <city>哈尔滨</city>
                <city>大庆</city>
            </cities>
        </province>
        <province>
            <name>广东</name>
            <cities>
                <city>广州</city>
                <city>深圳</city>
                <city>珠海</city>
            </cities>
        </province>
        <province>
            <name>台湾</name>
            <cities>
                <city>台北</city>
                <city>高雄</city>
            </cities>
        </province>
        <province>
            <name>新疆</name>
            <cities>
                <city>乌鲁木齐</city>
            </cities>
        </province>
    </country>

    用JSON表示如下

    {
        "name": "中国",
        "province": [{
            "name": "黑龙江",
            "cities": {
                "city": ["哈尔滨", "大庆"]
            }
        }, {
            "name": "广东",
            "cities": {
                "city": ["广州", "深圳", "珠海"]
            }
        }, {
            "name": "台湾",
            "cities": {
                "city": ["台北", "高雄"]
            }
        }, {
            "name": "新疆",
            "cities": {
                "city": ["乌鲁木齐"]
            }
        }]
    }

    由上面的两段代码可以看出,JSON 简单的语法格式和清晰的层次结构明显要比 XML 容易阅读,并且在数据交换方面,由于 JSON 所使用的字符要比 XML 少得多,可以大大得节约传输数据所占用的带宽。

    AJAX简介

    AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

    • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
    • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

    AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

    示例:

    页面输入两个整数,通过AJAX传输到后端计算出结果并返回。

    HTML部分代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="x-ua-compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>AJAX局部刷新实例</title>
    </head>
    <body>
    
    <input type="text" id="i1">+
    <input type="text" id="i2">=<input type="text" id="i3">
    <input type="button" value="AJAX提交" id="b1">
    
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
      $("#b1").on("click", function () {
        $.ajax({
          url:"/ajax_add/",
          type:"GET",
          data:{"i1":$("#i1").val(),"i2":$("#i2").val()},
          success:function (data) {
            $("#i3").val(data);
          }
        })
      })
    </script>
    </body>
    </html>

    views.py

    def ajax_demo1(request):
        return render(request, "ajax_demo1.html")
    
    
    def ajax_add(request):
        i1=int(request.GET.get("i1"))
        i2=int(request.GET.get("i2"))
        ret=i1 + i2
        return JsonResponse(ret, safe=False)

    urls.py

    urlpatterns=[
        ...
        url(r'^ajax_add/', views.ajax_add),
        url(r'^ajax_demo1/', views.ajax_demo1),
        ...   
    ]

    AJAX语法

    $.ajax({
        url:"",  // 控制往哪里提交
        type:"POST",  // 请求的方法
        data:{},  // 请求的参数
        success:function(arg){
            // 收到响应之后要做的事
        }
    })

    AJAX常见应用情景

    搜索引擎根据用户输入的关键字,自动提示检索关键字。

    还有一个很重要的应用场景就是注册时候的用户名的查重。

    其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。

    • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
    • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!


    当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询名为lemontree7777777的用户是否存在,最终服务器返回true表示名为lemontree7777777的用户已经存在了,浏览器在得到结果后显示“用户名已被注册!”。

    • 整个过程中页面没有刷新,只是局部刷新了;
    • 在请求发出后,浏览器不用等待服务器响应结果就可以进行其他操作;

    AJAX的优缺点

    优点

    • AJAX使用JavaScript技术向服务器发送异步请求;
    • AJAX请求无须刷新整个页面;
    • 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;

    jQuery实现的AJAX

    最基本的jQuery发送AJAX请求示例

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="x-ua-compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>ajax test</title>
      <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    </head>
    <body>
    <button id="ajaxTest">AJAX 测试</button>
    <script>
      $("#ajaxTest").click(function () {
        $.ajax({
          url: "/ajax_test/",
          type: "POST",
          data: {username: "Q1mi", password: 123456},
          success: function (data) {
            alert(data)
          }
        })
      })
    </script>
    </body>
    </html>

    views.py

    def ajax_test(request):
        user_name=request.POST.get("username")
        password=request.POST.get("password")
        print(user_name, password)
        return HttpResponse("OK")

    $.ajax参数

    data参数中的键值对,如果值值不为字符串,需要将其转换成字符串类型。

    $("#b1").on("click", function () {
        $.ajax({
          url:"/ajax_add/",
          type:"GET",
          data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
          success:function (data) {
            $("#i3").val(data);
          }
        })
      })

    AJAX请求如何设置csrf_token

    方式1

    通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。

    $.ajax({
      url: "/cookie_ajax/",
      type: "POST",
      data: {
        "username": "rum2",
        "password": 123456,
        "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val()  // 使用JQuery取出csrfmiddlewaretoken的值,拼接到data中
      },
      success: function (data) {
        console.log(data);
      }
    })

    方式2

    通过获取返回的cookie中的字符串 放置在请求头中发送。

    注意:需要引入一个jquery.cookie.js插件。

    $.ajax({
      url: "/cookie_ajax/",
      type: "POST",
      headers: {"X-CSRFToken": $.cookie('csrftoken')},  // 从Cookie取csrf_token,并设置ajax请求头
      data: {"username": "rum", "password": 123456},
      success: function (data) {
        console.log(data);
      }
    })

    或者用自己写一个getCookie方法:

    function getCookie(name) {
        var cookieValue=null;
        if (document.cookie && document.cookie !=='') {
            var cookies=document.cookie.split(';');
            for (var i=0; i < cookies.length; i++) {
                var cookie=jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1)===(name + '=')) {
                    cookieValue=decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    var csrftoken=getCookie('csrftoken');

    每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。

    function csrfSafeMethod(method) {
      // these HTTP methods do not require CSRF protection
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    
    $.ajaxSetup({
      beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
          xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
      }
    });

    序列化

    Django内置的serializers

    def books_json(request):
        book_list=models.Book.objects.all()[0:10]
        from django.core import serializers
        ret=serializers.serialize("json", book_list)
        return HttpResponse(ret)

    我们的数据中经常有日期时间,也就是datetime对象,而json.dumps是无法处理这样在类型的,那就需要通过自定义处理器来做扩展,如下:

    class JsonCustomEncoder(json.JSONEncoder):
        """
        自定义一个支持序列化时间格式的类
        """
    
        def default(self, o):
            if isinstance(o, datetime):
                return o.strftime("%Y-%m-%d %H:%M:%S")
            elif isinstance(o, date):
                return o.strftime("%Y-%m-%d")
            else:
                return json.JSONEncoder.default(self, o)
    
    
    def books_json(request):
        book_list=models.Book.objects.all().values_list("title", "publish_date")
        ret=json.dumps(list(book_list), cls=JsonCustomEncoder)
        return HttpResponse(ret)

    Bootstrap-sweetalert

    https://github.com/lipis/bootstrap-sweetalert
    $(".btn-danger").on("click", function () {
      swal({
        title: "你确定要删除吗?",
        text: "删除可就找不回来了哦!",
        type: "warning",
        showCancelButton: true,
        confirmButtonClass: "btn-danger",
        confirmButtonText: "删除",
        cancelButtonText: "取消",
        closeOnConfirm: false
        },
        function () {
          var deleteId=$(this).parent().parent().attr("data_id");
          $.ajax({
            url: "/delete_book/",
            type: "post",
            data: {"id": deleteId},
            success: function (data) {
              if (data.status===1) {
                swal("删除成功!", "你可以准备跑路了!", "success");
              } else {
                swal("删除失败", "你可以再尝试一下!", "error")
              }
            }
          })
        });
    })

    #科技##软件开发##python#

    山代有人才出,各领风骚数百年。

    前言

    Hello,大家好,我是编程三昧的作者隐逸王,小小前端一枚。

    自昨天发了《还在死磕 Ajax?那可就 out 了!》一文后,收到了一些大家的一些评论,评论都很走心,也很有深度。

    说实话,虽然我在尽可能努力地回复大家的问题,但还是避免不了对其中一些概念理解的模棱两可的情况,有幸得到同仁们的指点,比如:

    感谢各位的不吝赐教,让我在成长的道路上又前进了几分。

    现在总结一下,评论区涉及到的主要问题如下:

    • Fetch 和 Axios/Ajax 是什么关系
    • Fetch 真的会取代 Ajax 吗
    • 有封装良好的 Fetch 工具库推荐吗

    为了不辜负大家的热情,我在这里试着解释一下这些问题,如有疏漏,还请海涵!

    概念和特性

    首先,我们来了解一下 Ajax、Axios 和 Fetch 它们各自的概念。

    Ajax

    英文全称为 Asynchronous JavaScript + XML ,翻译过来就是异步JavaScript和XML

    它是用来描述一种使用现有技术集合的“新”方法的,这里的“新”方法主要涉及到: HTML 或 XHTML、CSS、 JavaScript、DOM、XML、XSLT,以及最重要的 XMLHttpRequest。

    当使用结合了这些技术的 AJAX 模型以后, 网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。

    Ajax 是一个概念模型,是一个囊括了众多现有技术的集合,并不具体代指某项技术。

    Ajax 最重要的特性就是可以局部刷新页面

    Axios

    Axios 是一个基于 Promise 网络请求库,作用于 Node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和 Node.js中)。在服务端它使用原生 Node.js http 模块,而在客户端则使用 XMLHttpRequest。

    这里我们只关注客户端的 Axios,它是基于 XHR 进行二次封装形成的工具库。

    客户端 Axios 的主要特性有:

    • 从浏览器创建 XMLHttpRequests
    • 支持 Promise API
    • 拦截请求和响应
    • 转换请求和响应数据
    • 取消请求
    • 自动转换JSON数据
    • 客户端支持防御XSRF

    Fetch

    Fetch 提供了一个获取资源的接口(包括跨域请求)。

    Fetch 是一个现代的概念, 等同于 XMLHttpRequest。它提供了许多与 XMLHttpRequest 相同的功能,但被设计成更具可扩展性和高效性

    Fetch 的核心在于对 HTTP 接口的抽象,包括 Request、Response、Headers 和 Body,以及用于初始化异步请求的 global fetch。得益于 JavaScript 实现的这些抽象好的 HTTP 模块,其他接口能够很方便的使用这些功能。

    除此之外,Fetch 还利用到了请求的异步特性——它是基于 Promise 的。

    fetch() 方法必须接受一个参数——资源的路径。无论请求成功与否,它都返回一个 Promise 对象,resolve 对应请求的 Response。

    Fetch 和 Axios/Ajax 的关系

    通过上面对三者概念的解释,我们应该大体清楚它们之间的关系了,我在这里用图表示一下:

    针对上图,我解释一下:

    • Ajax 是一种代表异步 JavaScript + XML 的模型(技术合集),所以 Fetch 也是 Ajax 的一个子集
    • 在之前,我们常说的 Ajax 默认是指以 XHR 为核心的技术合集,而在有了 Fetch 之后,Ajax 不再单单指 XHR 了,我们将以 XHR 为核心的 Ajax 技术称作传统 Ajax
    • Axios 属于传统 Ajax(XHR)的子集,因为它是基于 XHR 进行的封装。

    Fetch 真的会取代 Ajax 吗?

    其实这个问题更准确的问法应该是:Fetch 真的会取代传统 Ajax ( XHR ) 吗?

    要回答这个问题,我们需要清楚以下几点:

    • 异步编程是 JavaScript 发展的大趋势,且绝大多数浏览器都已支持标准 Promise。
    • Fetch API 是浏览器自带的 API,且它是基于标准 Promise 的。
    • 传统 Ajax 原生写法结构比较混乱,不符合关注分离的原则,写过远程 XHR 的同学应该深有体会。
    • Axios 是基于 XHR 封装的 Promise 请求库,用起来确实方便。

    基于以上几点,我的观点是Fetch 终会取代传统 Ajax,但过程可能比较漫长。

    虽然目前来看,传统 Ajax (比如 Axios 之类的)在使用规模上远远超过 Fetch,但要知道,这是 XHR 十来年累积下来的效果。

    封装得到的 Axios 在易用性上甩了原生 XHR 十万八千里,但毕竟是封装的,和原生的 Fetch 相比较,Axios 在出身上就已略输一筹,且原生的 API 天然上会支持更多的功能,使用上会更加灵活。

    Fetch 工具库推荐

    在昨天文章的评论区,有一位同学推荐了一个 Fetch 工具库,名为 Mande,有兴趣的同学可以去看看。

    总结

    以上就是针对 Fetch 和 Ajax 问题的一份简单解释,希望能够给大家带来启发。

    就我个人而言,倒是蛮期待 Fetch 能够取代传统 Ajax,技术的发展需要不断注入活力才行,我还能再干几十年,可不希望前端技术裹足不前,那样该多无聊 !

    ~

    ~本文完,感谢阅读!

    ~

    学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!

    大家好,我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢迎关注,希望大家多多指教!

    你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!

    知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!

    21章 Ajax与Comet

    21.1 XMLHttpRequest对象

    var xhr = new ?XMLHttpRequest();

    21.1.1 XHR的用法

    调用的第一个方法是open()

    xhr.open(method,url,false)
    • method:get和post
    • url:请求的目标url
    • false/true:是否异步发送请求。

    注:

    1、如果url不是绝对路径,那么就是相对于当前页面。

    2、open语句并不会立刻发送请求,需要send()方法。

    3、只能向同一个域中使用相同端口和协议的URL发送请求。

    要发送请求,需要再使用send方法:

    xhr.send(null)

    send方法的参数是指要发送的数据,如果没有的话需要写null。一般get方式不传数据,post方法需要传送数据。

    xhr收到响应后,会有下面这些属性:

    • status:http状态
    • statusText:http状态的说明
    • responseText:响应主体文本
    • responseXML:如果响应的内容类型是”text/xml”或”application/xml”,其中将保存着响应数据的XML文档

    接到响应后,首先检查status,确定是否成功返回:

    1、200响应成功;

    2、304请求的资源没有被修改,可使用缓存内容;

    可使用下面的代码检测响应状态:

    xhr.open("get", "example.txt", false);
    xhr.send(null);
    if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304) {
        alert(xhr.responseText);
    } else {
        alert("Request was unsuccessful: " + xhr.status);
    }

    发送异步请求时,需要监控readyState属性,该属性有如下几个值:

    • 0:未初始化。尚未调用open()方法
    • 1:启动。已调用open()方法,还未调用send()方法
    • 2:发送。已调用send()方法,还未接到响应
    • 3:接收。已收到部分响应数据
    • 4:完成。已收到全部响应数据

    每次readyState的值变化一次,就会触发一次readystatechange事件,所以可以在这个事件来检查readyState的值。

    xhr.onreadystatechange = function () {
        if (xhr.readyState ==4){
            if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304){
                alert(xhr.responseText);
            } else{
                alert("Request was unsuccessful" + xhr.status);
            }
        }
    };

    由于并不是所有浏览器都支持DOM2,所以采用DOM0级的方法来添加事件处理程序。

    21.1.2 HTTP头部信息

    头部信息有以下内容:

    • Accept:浏览器能够处理的内容类型。
    • Accept-Charset:浏览器能够显示的字符集。
    • Accept-Encoding:浏览器能够处理的压缩编码。
    • Accept-Language:浏览器当前设置的语言。
    • Connection:浏览器与服务器之间连接的类型。
    • Cookie:当前页面设置的任何Cookie。
    • Host:发出请求的页面所在的域。
    • Referer:发出请求的页面的URI。注意,HTTP规范将这个头部字段拼写错了,而为保证与规范一致,也只能将错就错了。(这个英文单词的正确拼法应该是referrer。)
    • User-Agent:浏览器的用户代理字符串。

    在open()方法之后,send()方法之前,通过调用setRequestHeader()可设置请求头:

    xhr.setRequestHeader("Host","https://www.baidu.com");

    使用getResponseHeader(“Host”)可以相应的值;

    使用getAllResponseHeaders()可以得到一个包含所有头部信息的长字符串。

    var myHeader= xhr.getResponseHeader("Host");
    var allHeaders= xhr.getAllResponseHeaders();

    21.1.3 GET请求

    GET请求是将查询字符串经过编码(encodeURIComponent)后拼接到URL后面的。

    下面的函数的作用是将查询字符串经过编码后拼接到URL后面:

    // 对查询参数进行编码并拼接
    function addURLParam(url,name,value) {
        url +=(url.indexOf("?")==-1 ? "?" : "&");
        url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
    }

    那么完整的请求如下:

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (xhr.readyState ==4){
            if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304){
                var myHeader= xhr.getResponseHeader("Host");
                var allHeaders= xhr.getAllResponseHeaders();
            } else{
                alert("Request was unsuccessful" + xhr.status);
            }
        }
    };
    xhr.open("get","example.html",true);
    xhr.setRequestHeader("Host","https://www.baidu.com");
    xhr.send(null);

    注:我在页面上写了个按钮和div区域,点击按钮时想向某站发送请求,然后将响应写到div中,出现了以下的错误:

    Refused to set unsafe header "User-Agent"

    Access to XMLHttpRequest at 'file:///K:/%E….' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

    我本来是打算利用js来像python那样实现爬取内容的,但发现不行。

    21.1.4 post请求

    function submitData() {
        var xhr=createXHR();
        xhr.onreadystatechange= function () {
            if (xhr.readyState ==4) {
                if ((xhr.status >=200 && xhr.status < 300) || xhr.status ==304) {
                    alert(xhr.responseText);
                } else {
                    alert("Request was unsuccessful: " + xhr.status);
                }
            }
        };
        xhr.open("post", "postexample.php", true);
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        var form= document.getElementById("user-info");
        xhr.send(serialize(form));
    }

    post请求在open中的第一个参数是get,在send中是经过序列化的字符串,具体见serialize函数。

    21.2 XMLHttpRequest 2级

    21.2.1 FormData

    FormData类型可以方便的对数据进行序列化,这个主要是用在post方式:

    var data= new FormData();
    data.append("name","伍德春");

    也可以直接将form作为实例化的参数:

    var data= new FormData(document.forms[0]);

    创建好data后,就可以将其作为send()方法的参数进行发送了。

    xhr.send(new FormData(document.forms[0]));

    21.2.2 超时设定

    在xhr.open与xhr.send之间,通过xhr.timeout=1000来设定超时时间,通过xhr.ontimeout=function(){//超时处理代码};来作为超时处理程序。

    21.2.3 overrideMimeType()

    使用此方法可以保证把响应当作指定的类型来处理,方法需要在open与send之间

    // 设置为XML
    xhr.overrideMimeType("text/xml");

    21.3 进度事件

    • loadstart:在接收到响应数据的第一个字节时触发。
    • progress:在接收响应期间持续不断地触发。
    • error:在请求发生错误时触发。
    • abort:在因为调用abort()方法而终止连接时触发。
    • load:在接收到完整的响应数据时触发。
    • loadend:在通信完成或者触发error、abort 或load 事件后触发。

    21.3.2 progress事件

    可以利用progrss事件动态的更新进度:

    xhr.onprogress = function (event) {
        var divStatus= document.getElementById("status");
        if (event.lengthComputable){
            divStatus.innerHTML = "已接收" + event.position + "/" + event.totalSize + "字节";
        }
    };

    这个事件处理程序的指定需要在xhr.open()方法之前。

    21.4 跨源资源共享CORS(Cross-Origin Resource Sharing)

    XHR对象只能访问与包含它的页面位于同一域中的资源。

    xhr.setRequestHeader("Origin","https://www.baidu.com");

    21.5 其他跨域技术

    21.5.1 图像ping

    21.5.2 JSONP

    JSON with padding填充式JSON或参数式JSON,即在请求参数中指定回调函数。

    21.5.3 Comet

    Comet是一种服务器向页面推送数据的技术。能够让信息近乎实时的推送到页面上,非常适合处理体育比赛的分数和股票报价(也适合公司车间展示信息)。

    21.5.4 服务器发送事件