zoukankan      html  css  js  c++  java
  • 一点对原生HTTP请求的理解与总结

    全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/10946165.html,多谢,=。=~

    术语

    HTTP:超文本传输协议,规定Web浏览器如何从Web服务器获取文档和向Web服务器提交表单内容,以及Web服务器如何响应这些请求和提交;

    (HTTP不在脚本控制下,只当用户点击链接、提交表单、输入URL时发生。但是js可操纵HTTP,例如设置window对象的location属性、调用表单的submit()方法会初始化HTTP请求,页面会重新加载。)

    Ajax:使用脚本操纵HTTP的Web应用架构,实现与Web服务器的数据交换,不会导致页面重载,客户端从服务器“拉”数据,可利用XMLHttpRequest对象实现;

    Comet:使用脚本操纵HTTP的Web应用架构,与Ajax相反,服务器向客户端“推”数据,可利用EventSource对象实现;

    XMLHttpRequest:定义了用脚本操纵HTTP的API;

    (XMLHttpRequest对象支持包括XML在内的任何基于文本的格式,能用于HTTP和HTTPS请求,涉及HTTP请求或响应的所有活动)

    XMLHttpRequest的使用

    实例化(IE7及以后):

    var request = new XMLHttpRequest();

    模拟XMLHttpRequest构造函数(IE5、IE6):

    if (window.XMLHttpRequest === undefined) {
        window.XMLHttpRequest = function() {
            try {
                return new ActiveXObject("MSXML2.XMLHttp.6.0");
            }
            catch (e1) {
                try {
                    return new ActiveXObject("MSXML2.XMLHttp.3.0");
                }
                catch (e2) {
                    throw new Error("XMLHttpRequest is not supported");
                }
            }
        }
    }

    HTTP请求(请求的方法或动作、请求的URL、请求头、请求体):

    request.open("GET", "/log.php");    // 请求的方法、URL
    request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");   // 请求头
    request.send(null);   // 请求体

    HTTP响应(数字+文字的状态码、响应头、响应体):

    request.onreadystatechange = function() {
        // HTTP的请求状态readyState
        // 0:open尚未调用
        // 1:open已调用
        // 2:接收到头信息
        // 3:接收到响应主体
        // 4:响应完成
        
        // HTTP状态码status
        // 2xx:代表请求已成功被服务器接收、理解、并接受
        if(request.readyState === 4 && request.status === 200) {
            // responseText属性:MIME类型的文本响应,如:text/css
            // responseXML属性:Document对象类型,如:XML、XHTML
            console.log(request.responseText);
        }
    };

     响应解码

    request.onreadystatechange = function() {
        if (request.readyState === 4 && request.status === 200) {
            var type = request.getResponseHeader("Content-type");
            if (type.indexOf("xml") !== -1 && request.responseXML) {
                console.log(request.responseXML);   // Document对象响应
            } else if (type === "application/json"){
                console.log(JSON.parse(request.responseText));   // Json响应
            } else {
                console.log(request.responseText);   // 字符串响应
            }
        }
    };

    请求主体编码(POST请求)

    1、表单编码(对名字和值进行URL编码(即使用十六进制转义码替换特殊字符)、使用=分开编码后的名字和值、使用&连接名/值对)

    PS:<input type="submit">定义用于向表单处理程序(form-handler)提交表单的按钮,自带表单编码功能。

    POST请求必须设置请求头:

    request.open("POST",url);
    request.setRequestHeader("Content-type","application/x-www-form-urlencoded"); request.send(encodeFormData(data));

     GET请求只需跟在url连接后即可:

    request.open("GET", url + "?" + encodeFormData(data));
    request.send(null);

    表单编码函数encodeFormData:

    // 对象属性的表单编码
    function encodeFormData(data) {
        if (!data) return "";   // 如果data非对象则返回空字符串
        var paris = [];   // 保存名=值对
        for(var name in data) {
            if (!data.hasOwnProperty(name)) continue;   // 跳过继承属性
            if (typeof data[name] === "function") continue;   // 跳过方法
            var value = data[name].toString();   // 将值转换为字符串
            name = encodeURIComponent(name.replace("20%", "+"));   // 编码名字
            value = encodeURIComponent(value.replace("20%", "+"));   // 编码值
            paris.push(name + "=" +value);
        }
        return paris.join("&");   // 使用"&"连接名/值对
    }

    2、JSON编码(使用JSON.stringify()方法)

    request.open("POST",url);
    request.setRequestHeader("Content-type","application/json");
    request.send(JSON.stringify(data));

    3、XML编码(send方法中传递XML Document对象)

    <query>
        <find zipcode="02134" radius="1km">
            pizza
        </find>
    </query>
    function createXML(what, where, radius) {
        // Create an XML document with root element <query>
        var doc = document.implementation.createDocument("", "query", null);
        var query = doc.documentElement;   // <query>元素
        var find = doc.createElement("find");   // 创建<find>元素
        query.appendChild(find);   // 把<find>添加至<query>中
        find.setAttribute("zipcode", where);   // 设置<find>的属性
        find.setAttribute("radius", radius);
        find.appendChild(doc.createTextNode(what));   // 设置<find>的内容
        return doc;
    }
    
    // 会自动设置Content-type头
    request.send(createXML("pizza", "02134", "1km"));

    4、文件上传

     HTML表单<input type="file">始终能上传文件;XMLHTTPRequest无法实现;XHR2可以通过向send()方法传入File对象实现(文件类型是更通用的二进制大对象Blob类型中的一个子类型)。

    5、multipart/form-data请求

    当HTML表单同时包含文件上传元素和其他元素时,必须使用Content-type为multipart/form-data的特殊方式提交表单,该编码使用长“边界”字符串把请求主体分离成多个部分。

    XHR2定义了新的FormData API,容易实现多部分请求主体(使用FormData()构造函数创建FormData对象,然后按需多次调用这个对象的append()方法把个体的“部分”(字符串、File或Blob对象)添加到请求中)。

    function createFormData(data) {
        if (typeof FormData === "undefined") {
            throw new Error("FormData is not implemented");
        }
        var formData = new FormData();
        for(var name in data) {
            if (!data.hasOwnProperty(name)) continue;
            var value = data[name];
            if (typeof value === "function") continue;
            formData.append(name, value);
        }
        return formData;
    }
    
    request.send(createFormData({user: "aaa", text: "bbb"}));

    HTTP请求无法完成的3种情况

    1、timeout事件:请求超时;

    2、abort事件:请求中止;

    3、error事件:比如太多重定向这样的网络错误会阻止请求完成;

  • 相关阅读:
    导航控制器生产,push,pop,root,index
    DNSserver内置笔记本
    解决“Dynamic Web Module 3.0 requires Java 1.6 or newer.”错误
    ssh配置连接
    在UITouch事件中画圆圈-iOS8 Swift基础教程
    iOS之UITableViewCell左右滑动效果
    iOS UIView非常用方法及属性详解
    IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
    UIColor,CGColor,CIColor三者的区别和联系
    iOS中正确的截屏姿势
  • 原文地址:https://www.cnblogs.com/dreamsqin/p/10946165.html
Copyright © 2011-2022 走看看