zoukankan      html  css  js  c++  java
  • ajax与axios

    今天被问到用没用过ajax axios,我回答 经常用axios,但ajax用的比较少,额。。。

    首先,axios是ajax的promise封装版,跟jquery是ajax的回调函数封装版类似

    ajax (async jasvascript And xml)

    [r1] Ajax文档 (MDN) 本文大篇幅参考MDN

    [r2] AJAX (阮一峰)

    1.1 ajax

    1)ajax介绍

    ajax (async jasvascript And xml)即异步JavaScript和XML,但

    尽管X在Ajax中代表XML, 但由于JSON的许多优势,比如更加轻量以及作为Javascript的一部分,目前JSON的使用比XML更加普遍。JSON和XML都被用于在Ajax模型中打包信息。

    ajax有很多种方式:1XHR 2Fetch API 3Server-sent事件(使用服务器发送事件)

    fetch 和 server-sent,在IE中都不被支持,我们把重点放在XHR上

    2)XMLHttpRequest API是Ajax的核心

    首先看看一些常用属性和方法:

    名称 作用
    onreadystatechange 该属性指定一个响应的回调
    readyState 请求状态:0 1 2 3 4请求完毕
    4 === xhr.DONE
    status 响应状态码
    一些方法
    open 初始化一个请求
    setHeaders myReq.setRequestHeader(header, value); 设置头部信息必须在open和send之间
    send 发送请求
    一些事件
    onerror 错误发生的回调
    timeout 超时回调
    onload

    在来看一个完整例子

    let httpRequest;
    if (window.XMLHttpRequest) {
        httpRequest = new XMLHttpRequest()
    } else {
        console.log('出错了,请升级您的浏览器,目前版本不支持发送HTTP请求!')
    }
    function makeRequest() {
        // 1 请求逻辑
        httpRequest.onreadystatechange = resHandler
        httpRequest.open('GET', 'http://www.baidu.com', true)
        // 请求方法必须大写,第三参数标识是否异步
        httpRequest.send()
    }
    
    function resHandler() {
        // 2 响应数据处理逻辑
        console.log('[]:', httpRequest.readyState)
        if (httpRequest.readyState === XMLHttpRequest.DONE) { // 或者===4
            if (httpRequest.status === 200) {
                console.log('收到服务器响应数据')
                console.log('[返回为字符串]:', httpRequest.responseText)
    
            } else {
                console.log('出错!', httpRequest.status)
            }
        }
    }
    
    makeRequest()
    // 启动
    

    ajax用于无刷新请求数据,它的一个经典案例是 文件上传

    1.2 文件上传

    提交表单和上传文件共有两种方法:

    • 使用ajax,灵活,但复杂
    • FormData API,简单,但无法使用JSON.stringify转化为一个对象字符串(why?),因为xhr.send(new FormData(elForm))无法拿到数据
    1)使用ajax提交数据

    有两个原因,这种方法摒弃:1代码较为复杂 2兼容性差

    但我在阅读的时候,有一个疑惑,在MDN上说:

    在使用ajax上传文件的时候,发送二进制内容的最佳途径是通过 ArrayBuffersBlobs 结合 send() 方法甚至 FileReader API 的 readAsArrayBuffer() 方法。但是,自从该脚本的目的变成处理 可字符串化 的原始数据以来,我们使用 sendAsBinary() 方法结合 FileReader API 的 readAsBinaryString() 方法。同样地,上述脚本仅当你处理小文件时行之有效。如果不打算上传二进制内容,就考虑使用 FormData API 来替代。

    最后一句,如果处理不打算上传二进制内容就用FormData,就用FormData API代替

    这里的二进制内容指的是什么?图片?可执行文件?

    这里指的是二进制对象,能够被JSON.parse反序列化的字符串对象

    2)使用FormData API提交数据【重点】

    这也是目前通用方法

    直接上案例,简单

    <script>
        function AJAXSubmit (oFormElement) {
            if (!oFormElement.action) { return; }
            var oReq = new XMLHttpRequest();
            oReq.onload = ajaxSuccess();
            if (oFormElement.method.toLowerCase() === "post") {
                oReq.open("post", oFormElement.action);
                oReq.send(new FormData(oFormElement));
                # 核心代码
                # 下面是兼容GET请求,作为扩展内容【了解】
            } else {
                var oField, sFieldType, nFile, sSearch = "";
                for (var nItem = 0; nItem < oFormElement.elements.length; nItem++) {
                    oField = oFormElement.elements[nItem];
                    if (!oField.hasAttribute("name")) { continue; }
                    sFieldType = oField.nodeName.toUpperCase() === "INPUT" ?
                        oField.getAttribute("type").toUpperCase() : "TEXT";
                    if (sFieldType === "FILE") {
                        for (nFile = 0; nFile < oField.files.length;
                             sSearch += "&" + escape(oField.name) + "=" + escape(oField.files[nFile++].name));
                    } else if ((sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") || oField.checked) {
                        sSearch += "&" + escape(oField.name) + "=" + escape(oField.value);
                    }
                }
                oReq.open("get", oFormElement.action.replace(/(?:?.*)?$/, sSearch.replace(/^&/, "?")), true);
                oReq.send(null);
            }
        }
    </script>
    
    <form action="register.php" method="post" enctype="multipart/form-data"
          onsubmit="AJAXSubmit(this); return false;">
        <fieldset>
            <legend>Upload example</legend>
            <p>
                姓名: <input type="text" name="firstname" /><br />
            </p>
            <p>
                您的照片:
                <input type="file" multiple name="photos[]">
            </p>
            <p>
                <input type="submit" value="Submit" />
            </p>
        </fieldset>
    </form>
    

    我们来看看FormData是什么?

    1.3 FormData

    1)首先,我们看3行代码【注意】

    // formData 只接受文件、Blob 或字符串,不能直接传递数组,所以必须循环嵌入
    for (let i = 0; i < photos.files.length; i++) {
        formData.append('photo', photos.files[i]);
    }
    

    会发现FormData不是一个简单的字典(map),因为字典中重名会被覆盖,FormData是一个对象,猜测内部维护了一个数组。以后可能会新增传入数组的方法。

    FormData特别简单,他可以接受的值有文件、Blob 和字符串

    var formData = new FormData();
    formData.append(key, value, [name]);
    
    [name] 第三个为可选参数,设置发送请求的头 Content-Disposition 指定文件名
    

    2)特殊用例

    var formData = new FormData(someFormElement);
    

    直接将一个Form标签解析,但注意只能解析具有name属性的字段

    formdata可以输入File,Blob,那么这两个又是什么?

    1.4 FileBlob

    Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。

    File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。通常情况下,File对象的来源为input标签输入的 FileList对象数组,File没有啥特殊功能,暂不关注。

    首先,我们来看一下Blob如何创建

    var aBlob = new Blob( array, options );
    

    创建一个Blob对象试试:

    var aFileParts = ['<a id="a"><b id="b">hey!</b></a>']; // 一个包含DOMString的数组
    var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
    

    刚刚说Blob中可以放ArrayBuffer,来看看它是什么

    1.4.1 ArrayBuffer

    ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。它是一个字节数组,通常在其他语言中称为“byte array”。

    最基本的

    const buffer = new ArrayBuffer(8);
    // 创建8个字节的缓冲区
    
    var view   = new Int32Array(buffer);
    // 用一个有符号32位类型化数组来用这个缓冲区
    

    典型案例,从文件中获取buffer

    function file2buffer(file){
        return new Promise((re,rj)=>{
            const rd = new FileReader()
    
            rd.onload = e => re(e.target.result)
            rd.onerror = e => rj(rd.error)
            // 先监听,后读取
            rd.readAsArrayBuffer(file)
        })
    }
    

    上面相当于File转buffer,那么buffer转File呢?

    首先,来看看File构造函数

    var myFile = new File(bits, name[, options]);
    
    • bits一个包含ArrayBuffer,ArrayBufferView,Blob,或者 DOMString 对象的 Array — 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。
    • name USVString,表示文件名称,或者文件路径。
    // 那么转File就很简单
    new File([buf], filename);
    

    再看,Blob与Buffer的转换,其实Blob与File类似,所以把所有的File变成Blob就可以了。

    new Blob([buf], filename);
    
  • 相关阅读:
    Eclipse相关问题
    分词工具比较(转)
    package-info.java文件详解
    如何在大量jar包中搜索特定字符
    eclipse插件在线发布发布和版本更新(web site) 转
    Peer Code Reviews Made Easy with Eclipse Plug-In
    Eclipse中Ant的配置与测试 转
    astyle 使用说明
    Eclipse远程调试出现“JDWP Transport dt_socket failed to initialize”的解决方案
    记录一个中括号的问题
  • 原文地址:https://www.cnblogs.com/nahaohao/p/14870258.html
Copyright © 2011-2022 走看看