• 前端架构师之01_JavaScript_Ajax


    1 Web基础知识

    1.1 Web服务器

    • Web服务器又称为网站服务器,主要用于提供网上信息浏览服务。
    • 常见的Web服务器软件有Apache HTTP Server(简称Apache)、Nginx等。

    浏览器与服务器交互

    • 在Web服务器中,请求资源又分为静态资源和动态资源。
    • 静态资源的特点:只要服务器没有修改这些文件,客户端每次请求到的都是同样的内容。
    • 动态资源的特点是内容可以动态发生变化,每次请求都需要计算处理。

    服务器端Web开发常用的技术有哪些?PHP、Java、ASP.NET、node.js

    1.2 HTTP协议

    • HTTP(HyperText Transfer Protocol)全称为超文本传输协议。
    • 用于规范客户端和服务器之间以指定的格式进行数据交互。

    HTTP是一种基于“请求”和“响应”的协议。

    当客户端与服务器建立连接后:

    • 客户端(浏览器)向服务器端发送一个请求,这个请求称为HTTP请求。
    • 服务器接收到请求后做出响应,称为HTTP响应。

    如何查看HTTP消息?借助浏览器的开发者工具。操作步骤:

    • ① 打开开发者工具。
    • ② 切换到Network选项。
    • ③ 刷新网页。

    HTTP协议

    • General表示基本信息。
    • Response Headers表示响应头。
    • Request Headers表示请求头。
    • 单击Response Headers或Request Headers右边的view source可以查看消息头的源格式。
    1.2.1 请求消息
    • 请求行
    • 请求头
    • 实体内容
    // 请求行
    // GET / HTTP/1.1
    // 请求头
    // Host: www.itheima.com
    // Connection: keep-alive	
    // User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML,…
    // Upgrade-Insecure-Requests: 1
    // Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/ …
    // Accept-Encoding: gzip, deflate
    // Accept-Language: zh-CN,zh;q=0.9
    
    // 请求行
    // POST /form.php HTTP/1.1
    // 请求头
    // Host: localhost
    // Content-Type: application/x-www-form-urlencoded
    // Content-Length: 20
    // 请求实体
    // user=Jim&pass=123456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    请求行的组成

    • 请求方式:有许多种,如GET是浏览器打开网页默认使用的方式,其他常用的还有POST方式。
    • 请求资源路径:是指URL地址中域名右边包括参数的部分,例如“/admin/save.php?id=1”。
    • HTTP版本:如HTTP/1.1、HTTP/1.0

    注:请求行各组成部分之间,使用空格隔开。

    请求头

    • 请求头的作用:请求头位于请求行之后,主要用于向服务器传递附加消息。
    • 请求头的组成:都是由头字段名称和对应的值构成,中间用冒号“:”和空格分隔。
    • 举例:浏览器可接受的数据类型、压缩方式、语言以及系统环境。

    实体内容

    • 内容编码:利用请求头Content-Type描述。编码格式按照
      标签的enctype属性来设定。默认值为application/x-www-form-urlencoded。文件上传为multipart/form-data。
    • 内存长度:利用请求头Content-Length描述。
    1.2.2 响应消息
    • 响应状态行
    • 响应头
    • 实体内容
    // 响应状态行
    // HTTP/1.1 200 OK
    // 响应头
    // Date: Thu, 02 Nov 2017 06:22:27 GMT
    // Server: Apache/2.4.23 (Win64) OpenSSL/1.0.2h PHP/5.6.28
    // Accept-Ranges: bytes
    // Content-Type: text/html
    
    // 实体内容
    // 
    // 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    响应状态行

    • HTTP版本:例如,HTTP/1.1。
    • 状态码:例如,200。
    • 描述信息:例如 OK 。

    响应状态行用于告知客户端本次响应的状态。

    状态码含义状态码含义
    200正常403禁止
    301永久移动404找不到
    302临时移动500内部服务器错误
    304未修改502无效网关
    401未经授权504网关超时

    状态码表示服务器对客户端请求的各种不同的处理结果和状态。

    响应头用于告知客户端本次响应的基本信息,包括服务器程序名、内容的编码格式、缓存控制等。

    请求头和响应头是浏览器和服务器之间交互的重要信息,由程序自动处理,通常不需要人为干预。

    实体内容

    • 网页 -> 图片
    • 服务器的响应实体内容有多种编码格式。
    • 服务器为了告知浏览器内容类型,会通过响应消息头中的Content-Type字段来描述。
    • 例如,网页的类型通常是“text/html”,这是一种MIME类型表示方式。

    MIME是目前大部分互联网应用程序通用的格式。MIME的表示方法为“大类别/具体类型”。

    MIME含义MIME含义
    text/plain普通文本(.txt)image/gifGIF图像(.gif)
    text/xmlXML文本(.xml)image/pngPNG图像(.png)
    text/htmlHTML文本(.html)image/jpegJPEG图像(.jpeg)
    text/cssCSS文本(.css)application/javascriptJavaScript程序(.js)

    浏览器会根据服务器响应的不同MIME类型采取不同的处理方式。

    • 遇到普通文本时直接显示。
    • 遇到HTML时渲染成网页。
    • 遇到GIF、PNG、JPEG等类型时显示为图像。

    如果浏览器遇到无法识别的类型时,在默认情况下会执行下载文件的操作。

    2 Web服务器搭建

    2.1 前后端交互

    • Web开发分为前端和后端。
    • 前端是面向用户的一端,即浏览器程序开发。
    • 后端则为前端提供服务,即服务器端程序开发。
    • 在动态网站中,许多功能是由前后端交互实现的。例如,用户注册和登录、发表评论、查询积分、余额等。
    • 这些操作可分为两类,一类是向服务器提交数据(表单交互),一类是向服务器查询数据( URL参数交互)。

    表单交互

    表单交互是指在HTML中创建一个表单,用户填写表单后提交给服务器,服务器收到表单后返回处理结果。

    URL参数交互

    URL参数经常用于浏览器向服务器提交一些请求信息。

    3 Ajax入门

    3.1 什么是Ajax

    Ajax:Asynchronous JavaScript And XML,异步JavaScript和XML技术。

    描述:不是一门新的语言或技术,是由JavaScript、XML、DOM、CSS等多种已有技术组合而成的一种浏览器端技术。

    功能:用于实现与服务器进行异步交互的功能。

    Ajax相对于传统的Web应用开发区别:

    • 传统Web工作流程

    • Ajax工作流程

    相较于传统网页,使用Ajax技术的优势具体有以下几个方面。

    • 减轻服务器的负担
    • 节省带宽
    • 用户体验更好

    3.2 创建Ajax对象

    创建Ajax对象

    • W3C标准

      var xhr = new XMLHttpRequest();
      
      • 1
    • 早期IE浏览器

      var xhr = new ActiveXObject('Microsoft.XMLHTTP');
      var xhr = new ActiveXObject('Msxml2.XMLHTTP');
      var xhr = new ActiveXObject('Msxml2.XMLHTTP.3.0');
      var xhr = new ActiveXObject('Msxml2.XMLHTTP.5.0');
      var xhr = new ActiveXObject('Msxml2.XMLHTTP.6.0');
      
      • 1
      • 2
      • 3
      • 4
      • 5

    3.3 Ajax向服务器发送请求

    • 创建一个新的HTTP:open()方法

      • open('method', 'URL' [, asyncFlag [, 'userName' [, 'password']]])
        
        • 1
      • method:用于指定请求方式,如GET、POST,不区分大小写。

      • URL:表示请求的地址。

      • asyncFlag:可选参数,用于指定请求方式,同步请求为false,默认为异步请求true。

      • userName和password:可选参数,表示HTTP认证的用户名和密码。

    • 设置HTTP请求头:setRequestHeader()方法

      • setRequestHeader('haeder', 'value')
        
        • 1
      • 参数都为字符串类型。

      • header表示请求头字段。

      • value为该字段的值。

      • 此方法必须在open()方法后调用。

    • 向Web服务器发送请求并接收响应:send()方法

      • send(content)
        
        • 1
      • content:用于指定要发送的数据,其值可为DOM对象的实例、输入流或字符串,一般与POST请求类型配合使用。

      • 注意:如果请求声明为同步,该方法将会等待请求完成或者超时才会返回,否则此方法将立即返回。

    在进行Ajax开发时,经常使用GET方式或POST方式发送请求。

    • GET方式适合从服务器获取数据。
    • POST方式适合向服务器发送数据。需要设置内容的编码格式,告知服务器用什么样的格式来解析数据。

    Ajax对象发送请求的方法。

    // GET
    var xhr = new XMLHttpRequest();         // 创建Ajax对象
    xhr.open('GET', 'test?a=1&b=2');    // 建立HTTP请求
    xhr.send();
    
    // POST
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'test?a=1&b=2');
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send('c=3&d=4');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    同步请求与异步请求

    Ajax对象open()方法的第3个参数用于设置同步请求和异步请求。两种方式的区别在于,是否阻塞代码的执行

    • 异步方式(默认):是非阻塞的,浏览器端的JavaScript程序不用等待Web服务器响应,可以继续处理其他事情。当服务器响应后,再来处理Ajax对象获取到的响应结果。

    • 同步方式:是阻塞的,当Ajax对象向Web服务器发送请求后,会等待Web服务器响应的数据接收完成,再继续执行后面的代码。

    由于同步请求的Ajax导致程序阻塞,会对用户体验造成不利影响,因此通常情况下不推荐使用同步请求。

    3.4 处理服务器返回的信息

    • 获取Ajax的当前状态:readyState属性

      • readyState属性用于获取Ajax的当前状态,状态值有5种形式。

        状态值说明解释
        0未发送对象已创建,尚未调用open()方法
        1已打开open()方法已调用,此时可以调用send()方法发起请求
        2收到响应头send()方法已调用,响应头也已经被接收
        3数据接收中响应体部分正在被接收。responseText将会在载入的过程中拥有部分响应数据
        4完成数据接收完毕。此时可以通过responseText获取完整的响应
      • 另外,Ajax状态的还可以通过“XMLHttpRequest.属性名”的方式获取。

        XMLHttpRequest.UNSENT;		// 对应状态值0
        XMLHttpRequest.OPENED;		// 对应状态值1
        XMLHttpRequest.HEADERS_RECEIVED;	// 对应状态值2
        XMLHttpRequest.LOADING;		// 对应状态值3
        XMLHttpRequest.DONE;			// 对应状态值4
        
        • 1
        • 2
        • 3
        • 4
        • 5
    • 感知Ajax状态的改变:onreadystatechange事件属性

      • onreadystatechange事件属性用于感知readyState属性状态的改变,每当readyState的值发生改变时,就会调用此事件。

        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            console.log(xhr.readyState);
        };
        console.log(xhr.readyState);
        xhr.open('GET', 'test.php');
        xhr.send();
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
    • 返回当前请求的HTTP状态码:status属性

      • status属性用于返回当前请求的HTTP状态码,值为数值类型。
      • 例如,当请求成功时,状态码为200。
      • 另外还有一个类似的属性statusText,值为字符型数据,包含了描述短语,如“200 OK”。
    • 获取响应信息:responseText属性、responseXML属性等

      • 当请求服务器成功且数据接收完成时,可以使用Ajax对象提供的相关属性获取服务器的响应信息。

        属性名说明
        responseText将响应信息作为字符串返回
        responseXML将响应信息格式化为XML Document对象并返回(只读)
      • responseXML属性在请求失败或相应内容无法解析时的值为null。

      • 需要注意的是,服务器在返回XML时应设置响应头Content-Type的值为text/xml或application/xml,否则会解析失败。

      • Ajax如何处理服务器返回的信息。

        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status < 200 || xhr.status >= 300 && xhr.status !== 304) {
                    alert('服务器异常');
                    return;
                }
                console.log(xhr.responseText);
            }
        };
        xhr.open('GET', 'hello.php');
        xhr.send();
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12

    URL参数编码转换

    • 在通过URL参数传递数据时,如果参数中包含特殊字符可能会出现问题。

    • 例如 “?” “=” “&”,这些字符已经被赋予了特定的含义。

    • 如果需要传递这些特殊字符,可以使用encodeURIComponent()进行URL编码。

      var str = encodeURIComponent('A&B C');
      var url = 'http://xxx/test?name=' + str;
      // 输出结果:http://xxx/test?name=A%26B%20C
      console.log(url);	
      
      • 1
      • 2
      • 3
      • 4
      • “&”被转换为“%26”。

      • 空格被转换为“%20”。

      • 当服务器收到已编码的内容之后,会对其进行解码,从而正确识别这些特殊字符。

    • 对于已经编码的字符串,可以使用decodeURIComponent()进行解码。

      var str = 'A%26B%20C';
      // 输出结果:A&B C
      console.log(decodeURIComponent(str));
      
      • 1
      • 2
      • 3

    4 数据交换格式

    前后端应用程序在进行数据交换时,如何确保它们都能识别?

    约定一种格式,确保通信双方都能够正确识别对方发送的信息。

    4.1 XML数据格式

    XML:eXtensible Markup Language,可扩展标记语言。

    与HTML都是标签语言,XML主要用于描述和存储数据,可以自定义标签。

    
    
    
    
    
    <booklist>
        <book>
            <name>三国演义name>
            <author>罗贯中author>
        book>
        <book>
            <name>水浒传name>
            <author>施耐庵author>
        book>
    
    booklist>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    当服务器返回的是一个XML格式的数据时,利用Ajax对象的responseXML属性即可对XML数据进行处理。

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            var data = xhr.responseXML;
            var booklist = data.getElementsByTagName('booklist')[0];
            console.log(booklist.childNodes);
            var book = booklist.children[0];
            console.log(book.children[0].innerHTML);               // 方式1
            console.log(book.children[0].firstChild);              // 方式2(会加上引号)
            console.log(book.children[0].firstChild.wholeText);    // 方式3
        }
    };
    xhr.open('GET', 'xml.php');
    xhr.send();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.2 JSON数据格式

    JSON:是一种轻量级的数据交换格式。

    特点:采用完全独立于语言的文本格式,这使得JSON更易于程序的解析和处理。

    与XML对比:使用JSON对象访问属性的方式获取数据更加方便,在JavaScript中可以轻松地在JSON字符串与对象之间转换。

    JSON格式的数据交互实现。

    var obj = {name: 'Tom', age: 24};     // 准备要发送的数据
    var json = JSON.stringify(obj);       // 将对象转换为JSON字符串
    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'json.php');
    xhr.onreadystatechange = function() {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            var obj = JSON.parse(xhr.responseText);    // 将JSON字符串转换为对象
            console.log(obj);
            /*
            console.log(typeof xhr.responseText);     // 查看服务器返回数据的类型:string
            eval('var obj = ' + xhr.responseText);    // 用eval()函数将字符型转成对象
            console.log(obj.name);                    // 输出结果:Tom
            console.log(obj.age);                     // 输出结果:24
          */
        }
    };
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send('json=' + encodeURIComponent(json));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    eval()函数

    JavaScript中的eval()函数可将传入的字符串当做JavaScript代码执行。

    console.log(typeof xhr.responseText); // 查看服务器返回数据的类型:string
    eval('var obj = ' + xhr.responseText);  // 用eval()函数将字符型转成对象
    console.log(obj.name);                         // 输出结果:Tom
    console.log(obj.age);                    	   // 输出结果:24
    
    • 1
    • 2
    • 3
    • 4

    eval()在设置参数时,如果传入的字符串不合法,会导致后面的代码也不执行,所以一般情况下不推荐使用它。

    5 跨域请求

    5.1 Ajax跨域问题

    • 域(Domain)是指网络中独立运行的单位。
    • 从网络安全角度来看,域是安全的边界,每个域都有自己的安全策略,不同域之间是隔离的,除非建立信任关系,否则无法互相访问。
    A网站 -> 利用Ajax读取用户在B网站中的余额 -> B网站
    A网站 <- 通过Ajax向A网站发送修改密码的请求 <- B网站
    
    • 1
    • 2

    跨域请求会导致网页失去安全性,因此浏览器阻止跨域请求。

    浏览器如何解决跨域问题带来的危害。

    遵循同源策略,同源是指请求URL地址中的协议、域名和端口都相同。

    非同源的URL地址

    问题URL-1URL-2
    域名不同http://www.example.com/1.htmlhttp://api.example.com/1.html
    协议不同http://www.example.com/1.htmlhttps://www.example.com/1.html
    端口不同http://www.example.com/1.htmlhttp://www.example.com:8080/1.html

    浏览器遵循“同源策略”带来的问题:给网站正常的跨域需求带来了难题。

    解决办法之一:为使受信任的网站之间能够跨域访问,HTML5提供了一个新的策略,就是Access-Control-Allow-Origin响应头。目标服务器通过该响应头可以指定允许来自特定URL的跨域请求,其值可以设置为任意URL或特定URL等。

    header('Access-Control-Allow-Origin: http://localhost:8081');
    
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://localhost:8082/8082');
    xhr.send();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.2 JSONP实现跨域请求

    JSONP:遵循浏览器的同源策略基础上实现跨域请求的一种方式。

    原理:与XMLHttpRequest无关,是利用