Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I_4 #4

Open
noopn opened this issue Aug 15, 2018 · 0 comments
Open

I_4 #4

noopn opened this issue Aug 15, 2018 · 0 comments

Comments

@noopn
Copy link
Owner

noopn commented Aug 15, 2018

XMLHttpRequest

在JavaScript发展的最初阶段,想知道提交一份表单的对错,必须传到服务器等待服务器的想应,而服务器相应的同时会刷新页面,如果表单的内容非常多,因为一个错误要重新填写,是非常头疼的一件事。
因此AJAX的出现正式为我们解决了这些问题。AJAX并不是一个方法,它只是一个概念。

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

AJAX 是一种用于创建快速动态网页的技术。

通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。

而实现异步与后台交互就需要使用XMLHttpRequest对象,他是浏览器的内置对象,所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。

下面是MDN(火狐开发者社区)的一些提示

XMLHttpRequest可以用于获取任何类型的数据,而不仅仅是XML,它还支持 HTTP以外的协议(包括文>件和ftp)。
如果您的通信需要从服务器接收事件或消息数据,请考虑通过EventSource接口使用 server-sent >events。对于 full-duplex 通信, WebSockets 可能是更好的选择。

用XMLHttpRequest 发起一次异步的Get请求

var xhr= new XMLHttpRequest(),
    method = "GET",
    url = "https://xxx.xxx.com/";

xhr.open(method, url, true);
xhr.onreadystatechange = function () {
  if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
    console.log(xhr.responseText)
  }
}
xhr.send();

通过XMLHttpRequest构造函数创建XMLHttpRequest对象

所有的属性方法都在XMLHttpRequest 对象的实例上,必须在所有其他方法被调用前调用构造函数。

xhr.open( ) 方法初始化一个请求

xhr.open(method, url, async, user, password);
open有两个必填的参数:
method(请求方法)包括,「GET」、「POST」、「PUT」、「DELETE」、等
url 一个String 类型的请求地址
Get方法带参数拼接在url后面,‘/list?page=5’,如果有非法字符 ‘ ’,@,#,中文字符需要用 encodeURIComponent转义
async 是一个可选值表示是否是异步请求,默认值为true, 推荐一直使用异步请求

使用onreadystatechange监听请求的状态

XMLHttpRequest.onreadystatechange 会在 XMLHttpRequest 的readyState 属性发生改变时触发 readystatechange 事件的时候被调用。

readyState 属性是什么?

xhr.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态,他是下面值之一

状态 描述
0 UNSENT (未初始化) (XMLHttpRequest)对象已经创建,但还没有调用open()方法。值为0表示对象已经存在,否则浏览器会报错:对象不存在。
1 OPENED (载入/正在发送请求) 对XMLHttpRequest对象进行初始化,即调用open()方法,根据参数(method,url,true),完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。
2 HEADERS_RECEIVED (交互/解析数据)正在解析响应内容,此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。值为3表示正在解析数据。
3 LOADING (交互/解析数据)正在解析响应内容,此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。值为3表示正在解析数据。
4 DONE (后台处理完成)响应内容解析完成,可以在客户端调用了 ,此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。

因此当xhr.readyState === 4 时表示请求操作已经完成,XMLHttpRequest.DONE 为xhr对象原型上的属性。如下图:
pic

xhr.status 表示的是响应状态码200表示成功。

xhr.send( )

方法用于发送 HTTP 请求。如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回。XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。

总结如何发起一个请求

  1. 创建xhr对象
  2. 用onreadystatechange 监听状态的变化
  3. xhr.open 初始化请求
  4. 如果是post请求设置请求头
  5. xhr.send 发起请求

为什么有人用onload 和 onreadystatechange 有什么区别

XHR2规范草案定义了进度事件Progress Events规范,XMLHttpRequest对象在请求的不同阶段触发不同类型的事件,所以它不再需要检査readyState属性。这个草案定义了与客户端服务器通信有关的事件。这些事件最早其实只针对XHR操作,但目前也被其他API(如File API)借鉴。本文将详细介绍进度事件

load:
响应接收完毕后将触发load事件,因此也就没有必要去检查readyState属性了。但一个完成的请求不一定是成功的请求,例如,load事件的处理程序应该检查XMLHttpRequest对象的status状态码来确定收到的是“200 OK”而不是“404 Not Found”的HTTP响应

   xhr.onload = function(){
        if(xhr.status == 200){
           //...
        }
    }

progress:
progress事件会在浏览器接收新数据期间周期性地触发。而onprogress事件处理程序会接收到一个event对象,其target属性是XHR对象,但包含着三个额外的属性:lengthComputable、loaded和total。其中,lengthComputable是一个表示进度信息是否可用的布尔值,loaded表示已经接收的字节数,total表示根据Content-Length响应头部确定的预期字节数。

//计算下载速度,预计剩余下载时间
var loopStartTime = ''; //一个事件周期的初始时间
var loopEndTime = '';//一个事件周期的结束时间
var loadedData = 0; //一个事件周期前已经加载的数据
xhr.onload = function(){
  loopStartTime = new Date().getTime();   //初次数据接收时间在onload中设置
  oloaded = 0;//设置刚开始的数据为0
}
xhr.onprogress = function(e){
  loopEndTime = new Date().getTime();//触发事件是设置结束时间
  var pertime = (loopEndTime - loopStartTime) / 1000;//一个事件周期执行的时间
  loopStartTime = new Date().getTime(); //重置开始时间等待下一个事件触发
  var perload = e.loaded - oloaded; //一个触发事件接收到的数据量 单位(b)
  var speed = perload / pertime;//单位b/s
  var bspeed = speed;
  var units = 'b/s';//单位名称
  if (speed / 1024 > 1) {
    speed = speed / 1024;
    units = 'k/s';
  }
  if (speed / 1024 > 1) {
    speed = speed / 1024;
    units = 'M/s';
  }
  speed = speed.toFixed(1); //单位和速度
  var resttime = ((evt.total - evt.loaded) / bspeed).toFixed(1);//剩余数据量/当前的下载速度 = 预计剩余时间
}

upload:

这个对象是不透明的,但是作为一个XMLHttpRequestEventTarget,可以通过对其绑定事件来追踪它的进度。  
除了为监控HTTP响应的加载定义的这些有用的事件外,XHR2也给出了用于监控HTTP请求上传的事件。在实现这些特性的浏览器中,XMLHttpRequest对象将有upload属性。upload属性值是一个对象,它定义了addEventListener()方法和整个progress事件集合,比如onprogress和onload(但upload对象没有定义onreadystatechange属性,upload仅能触发新的事件类型)
能仅仅像使用常见的progress事件处理程序一样使用upload事件处理程序。对于XMLHttpRequest对象,设置XHR.onprogress以监控响应的下载进度,并且设置XHR.upload.onprogress以监控请求的上传进度

xhr.upload.onprogress = function(e){}

其他事件:

HTTP请求无法完成有3种情况,对应3种事件。如果请求超时,会触发timeout事件。如果请求中止,会触发abort事件。最后,像太多重定向这样的网络错误会阻止请求完成,但这些情况发生时会触发error事件
可以通过调用XMLHttpRequest对象的abort()方法来取消正在进行的HTTP请求。调用abort()方法在这个对象上触发abort事件
调用abort()的主要原因是完成取消或超时请求消耗的时间太长或当响应变得无关时。假如使用XMLHttpRequest为文本输入域请求自动完成推荐。如果用户在服务器的建议达到之前输入了新字符,这时等待请求不再有用,应该中止
XHR对象的timeout属性等于一个整数,表示多少毫秒后,如果请求仍然没有得到结果,就会自动终止。该属性默认等于0,表示没有时间限制

var xhr = new XMLHttpRequest();
btn.onclick = function(){
    xhr.abort();
};
xhr.ontimeout = function(){
    console.log('The request timed out.');
}
xhr.timeout = 100;
xhr.onabort = function(){
    console.log("The transfer has been canceled by the user.");
}
xhr.onerror = function(){
    console.log("An error occurred while transferring the file.");    
}
xhr.onloadend = function(){
    console.log("请求结束");    
}

FormData和表单提交

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.
FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据具有同样形式。

xhr.upload.onprogress = function(e){}

FileReader

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
其中File对象可以是来自用户在一个元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的 DataTransfer对象,还可以是来自在一个HTMLCanvasElement上执行mozGetAsFile()方法后返回结果。
使用FileReader实现图片上传前预览:

document.getElementById("fileInput").onchange = function (e) {
  var file = e.target.files[0] || e.dataTransfer.files[0];
  var fileReader = new FileReader();
  fileReader.onload = function () {
    document.getElementById('someImg').setAttribute('src', fileReader.result);
  }
  fileReader.readAsDataURL(file);
} 
@noopn noopn changed the title 从XMLHttpRequest到FileReader I_4 Aug 16, 2018
@noopn noopn mentioned this issue Aug 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant