企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# AJAX ## 优缺点 优点: * 最大的一点是页面无刷新,页面与服务器通信效果很好 * 使用异步操作。不会打断用户操作。有更加迅速的反应能力。 缺点: * 浏览器不兼容,IE和人类浏览器可能会有不兼容的情况出现 ## 关于ajax与单线程机制 我们知道js是一个单线程机制的语言。在浏览器中,主要有一下四种线程: * GUI渲染线程 * js引擎线程 * 浏览器事件触发线程 * HTTP请求线程 他们是如何产生交互的呢? 通常线程的交互以事件的方式发生,通过回调的方式予以通知。事件回调又通过**先进先出**的方式存入**任务队列**的末尾。等到js引擎空闲时,任务队列中的任务就会排队被执行,这些回调一般有 setTimeout, setInterval, click, ajax异步请求等回调。 > 浏览器中, js引擎线程会循环从 任务队列 中读取事件并且执行, 这种运行机制称作 Event Loop (事件循环). 在ajax请求中,我们从新建一个XMLHttprequest 到open send方法的调用,都是一个同步执行的方法。在send方法内部开始,浏览器就会为网络请求发起HTTP请求线程,同时js引擎线程继续向下执行。在收到response时,触发HTTP线程的回调事件。**onreadystatechange**这个回调事件就像我们上面说的一样,没有被立即执行,反而放置到了**任务队列**中等到js引擎闲置之后,才开始依次触发。 在onreadystatechange中,很可能是有dom操作的,这时,js引擎线程会被挂起,转而执行GUI渲染线程,触发回流或重绘。js引擎再次运行时,GUI线程又被挂起等到js闲置时可能会执行。 > 除了 GUI渲染线程 和 js引擎线程 是互斥的. 其他线程相互之间, 都是可以并行执行的 ## readyState 只读属性 readyState记录了ajax调用中的所有可能状态。 一共有0-4五种可能取值。 * 0:未初始化 请求已经建立,但是未开始初始化,未调用open方法 * 1:初始化 请求已经建立,但未发送。已经调用open,但未调用send。 * 2:发送数据 请求已发送,send已经调用,已经收到响应头。 * 3:数据传送中 请求处理中,因响应内容不全, 这时通过responseBody和responseText获取可能会出现错误。 * 4:完成 数据接收完毕,此时可以通过responseBody与responseText获取完整响应数据。 ## onreadystatechange 此回调方法在readyState状态改变时触发,在一个收到响应的ajax请求周期中,这个方法会触发四次。所以可以在里面绑定一些操作。 ~~~ xhr.onreadystatechange = function(e){ if(xhr.readystate==4){ var s = xhr.status; if((s >= 200 && s < 300) || s == 304){ var resp = xhr.responseText; //TODO ... } } } ~~~ ## status 只读 表示http请求状态的状态码,默认初始为0,如果服务器没有显式的制定时,默认为200。 ## ajax的原生实现 ~~~ function ajax(options) { var url = options.url || ''; var type = options.type.toUpperCase() || 'GET'; var data = options.data || ''; var success = options.success || function () {}; var error = options.error || function () {}; var dataArr = []; if(!url) return; // 格式化参数 if (typeof data === 'object') { for (var key in data) { if (data.hasOwnProperty(key)) { dataArr.push(key + '=' + data[key]); } } } else { dataArr = data.split('&'); } // 生成XMLHttpRequest对象 var xhr = new XMLHttpRequest(); // 设置监听方法 xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { success(xhr.responseText, xhr); } else { error(xhr.statusText); } } } // 判断请求方法 if (type === 'GET') { url = url + '?' + dataArr.join('&'); xhr.open(type, url.replace(/\?$/g, ''), true); xhr.send(); } else if (type === 'POST') { xhr.open(type, url, true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send(dataArr.join('&')); } } ajax({ url: 'http://localhost:8000', type: 'get', data: 'name=sky&age=24', success: function (res) { console.log(res); }, error: function (err) { console.log(err); } }); ~~~ ## Ajax同步异步问题 一.什么是同步请求:(false) 同步请求即是当前发出请求后,浏览器什么都不能做,必须得等到请求完成返回数据之后,才会执行后续的代码,相当于是排队,前一个人办理完自己的事务,下一个人才能接着办。也就是说,当JS代码加载到当前AJAX的时候会把页面里所有的代码停止加载,页面处于一个假死状态,当这个AJAX执行完毕后才会继续运行其他代码页面解除假死状态(即当ajax返回数据后,才执行后面的function)。 二.什么是异步请求:(true) 异步请求就当发出请求的同时,浏览器可以继续做任何事,Ajax发送请求并不会影响页面的加载与用户的操作,相当于是在两条线上,各走各的,互不影响。 > 一般默认值为true,异步。异步请求可以完全不影响用户的体验效果,无论请求的时间长或者短,用户都在专心的操作页面的其他内容,并不会有等待的感觉。 > **关于两者不同:** 1. 异步:在异步模式下,当我们使用AJAX发送完请求后,可能还有代码需要执行。这个时候可能由于种种原因导致服务器还没有响应我们的请求,但是因为我们采用了异步执行方式,所有包含AJAX请求代码的函数中的剩余代码将继续执行。如果我们是将请求结果交由另外一个JS函数去处理的,那么,这个时候就好比两条线程同时执行一样。 2. 同步:在同步模式下,当我们使用AJAX发送完请求后,后续还有代码需要执行,我们同样将服务器响应交由另一个JS函数去处理,但是这时的代码执行情况是:在服务器没有响应或者处理响应结果的JS函数还没有处理完成return时,包含请求代码的函数的剩余代码是不能够执行的。就好比单线程一样,请求发出后就进入阻塞状态,直到解除阻塞,余下的代码才会继续执行。