全栈工程师应该具备的技术
前端
- html(5)+css(3)
- JavaScript(jQuery,vue,react…)
后端
- Java(jsp)
- Python
- Node
- PHP(php)
- C#(.net->dot net)(ASP.NET)
- C
数据库
- MySQL
- SqlServer
- oracle
- MongoDB(和node结合紧密)
自动化
- git/svn
- webpack(基于node运行的)
- 服务器部署工具iis/apache/nginx
客户端和服务器端怎样通信
面试题:当在浏览器地址栏输入地址,如:https://www.baidu.com,点击enter键后,获取百度首页面的这个过程都经历了什么?
** request浏览器请求阶段 **
1. 首先根据客户端输入的域名,到DNS服务器上进行反解析(通过域名找到对应服务器的外网IP)(域名解析==DNS解析,DNS服务器是进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器)
2. 通过找到的外网IP,找到对应的服务器
3. 通过在地址栏中输入的端口号(没输入时因为不同协议有自己默认端口号)找到服务器上发布的对应的项目
** response服务器响应阶段 **
4. 服务器获取到请求资源文件的地址,例如:news/product.html,把文件中的源代码找到
5. 服务器端会把找到的云代码返回给客户端(通过HTTP等协议返回)
** 浏览器自主渲染 **
6. 客户端接收到源代码后,会交给浏览器的内核(渲染引擎)进行渲染,最后由浏览器绘制出对应的页面
HTTP
- URI:统一资源标识符
- URL:统一资源定位符
- URN:统一资源名称
- URI=URL+URN
一个完整的URL组成
http://www.baidu.com/news/product.html?name=test&age=9#good
第一部分:传输协议
传输协议是用来完成客户端和服务端的数据(内容)的,类似于快递小哥。
- 客户端不仅可以向服务器发送请求,还可以把一些内容传递给服务器
- 服务器端也可以把内容返回给客户端
- 客户端和服务器端传输的内容总称为
HTTP报文
,这些报文信息都是基于传输协议完成传输的,客户端传递给服务器叫做请求(request),服务器返回给客户端叫做响应(response),request+response两个阶段统称为一个HTTP事务
(事务:一件完整的事情)。
HTTP事务
- 当客户端向服务器端发送请求,此时客户端和服务端会建立一个传输通道(连接通道),传输协议就是基于这个通道把信息进行传输的
- 当服务端接收到请求信息,把内容返回个客户端后,传输通道会自动销毁关闭
传输协议分类
HTTP
:超文本传输协议(客户端和服务端传输的内容除了文本以外,还可以传输图片、音视频等文件流[二进制编码/base64码]),以及传输xml格式的数据等),是目前市场上应用最广泛的传输协议HTTPS
:HTTP+SSL,它比HTTP更加安全,因为数据内容的传输通道是经过SSL
加密的(它需要在服务器端进行特殊的处理),所以涉及资金类的网站一般都是HTTPS协议的。FTP
:资源文件传输协议,一般用于客户端把资源文件(不是代码)上传到服务器端,货值从服务器端下载一些资源文件(一般ftp传输的内容会比HTTP这类协议传输的内容多)。
HTTP报文
- 起始行
请求起始行
相应起始行 - 首部(头部)
请求头:内置请求头、自定义请求头
响应头:内置响应头、自定义响应头
通用头:请求和响应都有 - 主体
请求主体
响应主体
请求XXX都是客户端设置的信息,服务器端获取这些信息
响应XXX都是服务器端设置的信息,客户端用来接收这些信息
总结:
- 客户端传递给服务器端数据
- URL问号传递参数
- 设置请求头
- 设置请求主体
- 服务端返回给客户端内容
- 设置响应头(例如服务器时间)
- 设置响应主体
第二部分:域名
设置域名其实就是给不好记忆的服务去外网IP设置了一个好记忆的名字
顶级域名(一级域名):qq.com
二级域名:www.qq.com、v.qq.com
三级域名:kbs.sports.qq.com
第三部分:端口号
在服务器发布项目的时候,,我们可以通过端口号区分当前服务器上不同的项目
一台服务器的端口号取值范围:0~65535之间。如果电脑上安装了很多程序,有一些渡口号是被占用了
HTTP:默认端口号80
HTTPS:默认端口号443
FTP:默认端口号21
对于上述是三个端口号其实是很重要的,如果被其他程序占用,则我们不能使用。所以服务器上一般禁止安装其他程序的
第四部分:请求资源文件的路径名称
在服务器中发布项目的时候,我们一般会配置一些默认文档:用户即使不输入请求文件的名称,服务器也会找到默认文档(一般默认文档都是index/default)
我们通常为了做SEO优化,会把一些动态页面的地址(xxx.php、xxx.asp)进行伪URL重写(需要服务器处理)
https://item.jd.com/4325427.html
不可能是有一个商品自己就单独些一个详情页,肯定是同一个详情页做的不同处理
1)第一种方案:
由后台语言根据详情页模板动态生成具体的详情页面
2)第二种方案:
当前页面就是一个页面,例如:detail.html/detail.php,我们做详情页面的时候,开发是按照detail.html?id=4325427来开发的,但是这种页面不方便做SEO优化,此时我们把真实的地址进行重写,重写为我们看到的4325427.html
第五部分:问号传参
?name=test&age=9
把一些值通过xxx=xxx的方式,放在一个URL的末尾,通过问号传递
[作用]
1)在AJAX请求中,我们可以通过问号传递参数的方式,客户端把一些信息传递给服务器,服务器根据传递信息的不一样返回不同的数据
//$.ajax(url,{});
//$.get(url,function(){});对于AJAX请求的特殊写法,原理还是基于AJAX方法实现的 $.post/$.script
$.ajax({
url:'getInfo?id=12'
});
//当前案例:我们传递给服务器的编号是多少,服务器端就会把对应编号人员信息给返回
2)消除AJAX请求中GET方式缓存
$.ajax({
url:'xxx?_=1122',
method:'get
})
//我们会在请求URL的末尾追加一个随机数_=随机数,保证每一次请求的URL都是不一样的,以此来消除GET请求遗留的缓存问题
3)通过URL传参传递参数的方式,可以实现页面之间信息的通信。例如:我们有两个页面A/B,A是列表页面,B是详情页,点击A中的某一条信息,进入到唯一的详情页B,如何展示不同的信息,这种操作就可以基于URL问号传递参数来实现了
第六部分:HASH值
#xxx
URL末尾传递的井号什么,就是HASH值(哈希值)
[作用]
1)页面中锚点定位
2)前端路由(SPA单页面开发)
web前端开发常用的优化技巧汇总
减少http请求次数或请求数据的大小
页面中每发送一次HTTP请求,都需要完成请求+响应的完整HTTP事务,会消耗一些时间,也可能会导致HTTP连接通道堵塞,为了提高页面加载速度和运行的性能,我们应该减少HTTP请求的次数和请求数据的大小
- 采用CSS雪碧图(CSS Sprit/CSS图片精灵)技术,把一些小图合并在一张大图上,使用的时候通过背景图片定位,定位到具体的某一张小图上
- 真实项目中,我们最好把CSS或者JS文件合并压缩。尤其是在移动端开发的时候,如果CSS或者JS内容不是很多,我们可以采用内嵌式,以此减少HTTP请求的次数,加快页面加载速度
1)CSS合并成一个,JS最好合并成一个
2)首先通过一些工具(例如:webpack)把合并后的CSS或者JS压缩成xxx.min.js,减少文件大小
3)服务器端开启资源文件的GZIP压缩
4) 通过一些自动化工具完成CSS以及JS的合并压缩,或者再完成LESS转CSS,ES6转ES5等操作,我们把这中自动化构建模式,称之为前端“工程化”开发 - 采用图片懒加载技术,在页面开始加载的时候,不请求真实的图片地址,而是用默认图占位,当页面加载完成后,再根据相关的条件依次加载真实的图片(减少页面首次加载HTTP请求的次数)
真实项目中,我们开始图片都不加载,页面首次加载完成,先把第一屏幕中可以看到的图片进行加载,随着页面滚动,再把下面区域中能够呈现出来的图片进行加载
根据图片懒加载技术,我们还可以进行扩充,数据的懒加载
1)开始加载页面的时候,我们只把首屏或者前两屏的数据从服务器端进行请求(有些网站首屏数据是后台渲染好,整体返回飞客户端呈现)
2)当页面下拉,滚动到那个区域,再把这个区域需要的数据进行请求(请求回来做数据绑定以及图片延迟加载等)
3)分页展示技术采用的也是数据的懒加载思想实现的:如果我们请求的数据是很多的数据,我们最好分批请求,开始只请求第一页的数据,当用户点击第二页(微博是下拉到一定距离后,再请求第二页数据)的时候在请求第二页数据 - 对于不经常更新的数据,最好采用浏览器的304缓存做处理(主要由服务器处理)
例如:第一次请求CSS和JS下来,浏览器会把请求的内容缓存起来,如果做了304处理用户再次请求css和js,只接从缓存中读取,不需要再去服务器获取(减少HTTP请求次数)
当用户强制刷新页面(CTRL+F5)或者当前缓存的css或js发生了变动,都会重新从服务器拉取
对于客户端来讲,我们还可以基于localStorage来做一些本地存储,例如:第一次请求的数据或者不经常更新的css和js,我们都可以把内容存储在本地,下一次页面加载,我们从本地中获取即可,我们设定一定期限或者一些标识,可以控制在某个阶段重新从服务器获取 - 使用字体图标代替一些页面中的位图(图片),这样不仅做适配的时候方便,更加轻量级,而且减少HTTP请求次数(类似于雪碧图)
- 如果当前页面中出此案audio或者video标签时,我们最好设置他们的
preload=none;
页面加载的时候,音视频资源不进行加载,播放的时候再加载(减少页面首次加载HTTP请求的次数)
preload=auto
:页面首次加载的时候就把音视频资源进行加载
prelooad=metadata
:页面首次加载的时候只把音视频资源的头部信息进行加载 - 在客户端和服务器端进行数据通信的时候,我们尽量采用JSON格式进行数据传输
1) JSON格式的数据,能够清晰明了的展示出数据结构,而且也方便我们自己获取和操作
2)相对于很早以前的XML格式传输,JSON格式的数据更加轻量级
3)客户端和服务器端都支持JSON格式数据的处理,处理起来非常方便
4)真实项目中,并不是所有的数据都要基于JSON,我们尽可能这样子,但是对于某些特殊需求(例如:文件流传输或文档传输),使用JSON就不合适了 - 采用
CDN
加速
CDN
:分布式(地域分布式)
关于编写代码时候的一些优化技巧
除了减少HTTP请求次数和大小可以优化性能,我们在编写代码的时候,也可以进行一些优化,让页面的性能有所提升(有刺些不好的代码编写习惯会导致页面性能消耗太大,例如:内存泄漏)
- 在编写JS代码的时候,尽量减少对DOM的操作
在JS中操作DOM是一个非常消耗性能的事情,但是我们又不可避免的操作DOM,我们只能尽量减少对于他的操作
[操作DOM的弊端]
1)DOM存在映射机制(JS中的DOM元素对象和页面中的DOM结构是存在映射机制的,一改则都改),这种映射机制是浏览器按照W3C标准完成对JS语言的构建和DOM的构建(其实就是构建了一个监听机制),操作DOM是同时要修改两个地方,相对于一些其他JS编程来说是消耗性能的
2)页面中的DOM结构改变或者样式改变,会触发浏览器的回流
(浏览器会把DOM结构重新进行计算,这个操作很耗性能)
和重绘
(把一个元素的样式重新渲染)。、 - 编写代码的时候,更多的使用异步编程
同步编程会导致:上面东西完不成,下面任务也做不了,我们开发的时候,可以把某一个区域模块都设置为异步编程,这样只要模块之间没有必然的先后顺序,都可以独立进行加载,不会受到上面模块的堵塞影响(用的不多)
尤其是AJAX数据请求,我们一般都要使用异步编程,最好是基于promise
设计模式进行管理(项目中经常使用fetch
、vue axios
等插插件进行AJA 请求处理,因为这些插件中就是基于promise
设计模式对AJAX进行的封装处理) - 在真实项目中,我们 尽可能避免一次性循环过多数据(因为循环操作是同步便编程)尤其是要避免while导致的死循环操作
- css选择器优化
1)尽量减少标签选择器的使用
2)尽可能少使用 ID选择器,多使用样式累选择器(通用性强)
3)减少选择器前面的前缀,例如:.headerBox ,nav .left a{}(选择器是从右向左查找的) - 避免使用CSS表达式
/*css表达式*/
.box{
background-color:expression((new Date()).getHours()%2?'red':'blue')
}
- 减少页面中的冗余代码,尽可能提高方法的重复使用率:“低耦合高内聚”
- 最好css放在head中,js放在body尾部,让页面加载的时候,先加载css,再加载js(先呈现页面,再给用户提供操作)
- js中避免使用
eval
1)性能消耗大
2)代码压缩后,容易出现代码执行错乱问题 - js中尽量减少闭包的使用
1)闭包会形成一个不销毁的栈内存,过多的栈内存累计会影响页面的性能
2)容易导致内存泄漏
闭包也有自己的优势:保存和保护,我们只能尽量减少,但是无可避免 - 在做DOM事件绑定的时候,尽量避免一个个的事件绑定,而是采用性能更高的
事件委托(事件代理)
来实现
把事件绑定给外层容器,当里面的后代元素相关行为被触发,外层容器绑定的方法也会被触发执行(冒泡传播机制导致),通过事件源是谁,我们做不同的操作即可 - 尽量使用CSS3动画代替JS动画,因为CSS3的动画或者变形都开启了硬件加速,性能比JS动画好
- 编写JS代码的时候尽可能使用设计模式来构建体系,方便后期的维护,也提高了扩充性
- css中减少对滤镜的使用,页面中也减少对于flash的使用
关于页面的SEO优化技巧
- 页面中杜绝出现死链接(404页面),而且对于用户输入一个错误页面,我们要引导到404提示页面中(服务器处理的)
- 避免浏览器中异常错误的抛出
1)尽可能避免代码出错
2)使用TRY CATCH做异常信息捕获 - 增加页面关键词优化
AJAX基础知识及核心原理解读
AJAX基础知识
什么是AJAX
async javascript and xml,异步的js和xml
xml:可扩展标记语言
、
作用是用来存储数据的(通过自己扩展的标记名称清晰的展示出数据结构)
ajax之所以称为异步的js和xml,主要原因是:当初最开始用ajax实现客户端和服务端数据通信的时候,传输的数据格式一般都是xml格式的数据,我们把它称之为异步的js和xml(现在一般都是基于json格式进行数据传输的)
异步的js
这里的异步不是说ajax只能基于异步进行请求(虽然建议都是使用异步编程的),这里的异步特指的是局部刷新
局部刷新VS全局刷新
在非完全前后点分离
项目中,前段开发只需要完成页面的制作,并且把一些基础的人机交互效果使用js完成即可,页面中需要动态呈现内容的部分都是后台开发工程师做数据绑定和基于服务器进行渲染的(服务器端渲染)
[优势]
1) 动态展示的数据在页面的源代码中可以看见,有利于SEO优化推广(有利于搜索引擎的收录和抓取)
2) 从服务器端获取的结果就已经是最后要呈现的结果了,不需要客户端做额外的事情,所以页面加载速度快(前提是服务器端处理的速度足够快),所以类似于京东、淘宝这些网站,首屏数据一般是经由服务器端渲染的
[弊端]
1)如果页面中存在需要实时更新的数据,每一次想要展示最新的数据,页面都要重新的刷星一次,这样肯定不行
2) 都交给服务器端做数据渲染,服务器端的压力太大,若干服务器处理不过来,页面呈现的速度更慢(所以京东淘宝这类网站,除了首屏是服务器端渲染的,其他屏一般都是客户端做数据渲染绑定)
3) 这种模式不利于开发(开发效率低)
目前市场上大部分项目都是前后端完全分离
的项目(也有非完全前后端分离的)
前后端完全分离的项目,页面中需要动态绑定的数据交给客户端完成渲染的
1) 把服务器端发送AJAX请求
2)把从服务器端获取的数据解析处理,拼接成为我们需要展示的HTML字符串
3)把拼接号的字符串替换页面中某一部分的内容(局部刷新),页面整体不需要重新加载,局部刷新即可
[优势]
1)我们可以根据需求任意修改页面中某一部分的内容改变(例如实时刷新即可),整体页面不刷新,性能好,体验号(所有表单验证,需要实时刷新的等需求都要基于AJAX实现)
2)有利于开发,提高开发效率
a)前后端的完全分离,后台不需要考虑前端如何实现,前端你也不需要后台用 什么技术,真正意义上实现了技术的划分
b)可以同时进行开发:项目开发开始,首先制定前后端交互的接口文档(文档中包含了,调取哪个接口或者那些数据等协议规范),后台把接口先写好(目前很多公司也需要前端自己拿NODE来模拟这些接口),客户端按照接口调取即可,后台再次去实现接口功能即可
[弊端]
1.不利于SEO优化,第一次从服务器端获取的内容不包含需要动态绑定的数据,所以页面的源代码中没有这些内容,不利于SEO收录,后期通过JS添加到页面中的内容并不会写在页面的源代码中
2.交由客户端渲染,首先需要把页面呈现,然后再通过JS的异步AJAX请求获取数据,然后数据绑定,然后数据绑定,浏览器再把动态增加的部分重新渲染,无形中浪费了一些时间,没有服务器端渲染页面呈现速度快
基于原生JS实现AJAX
//创建一个AJAX对象
let xhr=new XMLHttpRequest();//不兼容IE6以及更低版本浏览器(IE6:ASctiveXObject)
//打开请求地址(可以理解为一些基础配置,但是并没有发送请求)
xhr.open([method],[url],[async],[user name],[userr password]);
//监听AJAX状态改变,获取响应信息(获取响应头信息、获取响应主体信息)
xhr.onreadystatechange=()=>{
if(xhr.readyState===4&&xhr.status===200){
let result=xhr.responseText;//获取响应主体中的内容
}
}
//发送AJAX请求(括号中传递的内容就是请求主体的内容)
xhr.send(null);
分析第二步中细节点
xhr.open([method],[url],[async],[user name],[userr password]);
AJAX请求方式
共8种:get,post,put,head.delete,options,trace,connect
1、GET系列请求(获取)
- get
- delete:从服务器上删除某些资源文件
- -head:只想获取服务器返回的响应头信息(响应主题内容不需要获取)
- …
2、POST系列请求(推送) - post
- put:向服务器中增加制定的资源文件
- …
不管是哪一种请求方式,客户端都可以把信息传递给服务器,服务器也可以把信息返回给客户端,知识GET系列一般以获取为主(给的少,拿回来的多),而POST系列一般以推送为主(给的多,拿回来的少)
1)我们想获取一些动态展示的信息,一般使用GET请求,因为只需要向服务器发送请求,告诉服务器端我们想要什么,服务器端就会把需要的数据返回
2)在实现注册功能的时候,我们需要把客户输入的信息发送给服务器进行存储,服务器一般返回的是成功还是失败等状态,此时我们一般都是基于POST请求完成
** GET系列请求和POST系列请求,在项目实战中存在很多的区别 **
1、GET请求传递给服务器的内容一般没有POST请求传递给服务器的内容多
原因:GET
请求传递给服务器内容一般都是基于URL地址问号传递参数
来实现的,而POST
请求一般是基于设置请求主体
来实现的。
各浏览器都有自己关于URL最大长度限制(谷歌:8KB,火狐:7KB,IE:2KB),超过限制长度的部分,浏览器会自动截取掉,导致传递给服务器的数据缺失
理论上POST请求通过请求主体传递是没有大小限制的,真实项目中为了保证传输的速度,,我们也会限制大小(例如:上传的资料或者图片我们会做大小的限制)
2、GET请求很容易出现缓存(这个缓存不可控:一般我们都不需要),而POST不会出现缓存(除非自己做特殊处理)
原因:GET是通过URL问号传参传递给服务器信息,而POST是设置请求主体。
设置请求主体不会出现缓存,但是URL传递参数就会出现缓存
//每隔一分钟重新请求服务器端最新的数据,然后展示在页面中(页面中某些数据实时刷新)
setTimeout(()=>{
$.ajax({
url:'getList?lx=news',
...
success:result=>{
//第一次请求数据回来,间隔一分钟后,浏览器又发送一次请求,但是新发送的请求不管是地址还是传递参数都和第一次一样,
//浏览器很有可能会把上一次数据获取,而不是获取最新的数据
}
})
},60000);
//解决方案:每一次重新请求的时候,在URL的末尾追加一个随机数,保证每一次请求的地址不完全一致,就可以避免是从缓存中读取的数据
setTimeout(()=>{
$.ajax({
url:'getList?lx=news&_='+Math.random(),
...
success:result=>{
}
})
},60000);
3、GET请求没有POST请求安全(POST也并不是十分安全,只是相对安全)
原因:还是因为GET是URL传参给服务器
有一种比较简单的黑客技术:URL劫持,也就是可以把客户端传递给服务器的数据劫持掉,导致信息泄露。
URL:请求数据的地址(API地址)
真实项目中,后台开发工程师会编写一个API文档,在API文档中汇总了获取哪些数据需要使用哪些地址,我们按照文档操作即可
ASYNC:异步(SYNC同步)
设置当前AJAX请求是异步还是同步的,不写默认是异步(TRUE),如果设置为FALSE,则代表当前请求是同步的
用户名和密码
这两个参数一般不用,如果你请求的URL地址所在的服务器设定了访问权限,则需要我们提供可同行的用户名和密码才可以(一般服务器都是可以允许匿名访问的)
第三部分细节分析
//监听AJAX状态改变,获取响应信息(获取响应头信息、获取响应主体信息)
xhr.onreadystatechange=()=>{
if(xhr.readyState===4&&xhr.status===200){
let result=xhr.responseText;//获取响应主体中的内容
}
}
AJAX状态码
:描述当前AJAX操作的状态的
xhr.readyState
:包括五种
0:UNSEND 未发送,只要创建一个AJAX对象,默认值为零
1:OPENED 我们已经执行了xhr.open这个操作
2:HEADERS_RECEVED 当前AJAX的请求已经发送,并且已经接收到服务器端返回的响应头信息
3:LOADING 响应主体内容正在返回的路上
4:DONE 响应主体内容已经返回到客户端
HTTP网络状态码
:记录了当前服务器返回信息的状态
xhr.status
200
:成功,一个完整的HTTP事务完成(以2开头的状态码一般都是成功)
以3开头一般也是成功,只不过服务器端做了很多特殊的处理
301
:Moved Permanently 永久转移(永久重定向),一般应用于域名迁移
302
:Move temporarily 临时转移(临时重定向,新的HTTP版本中任务307是临时重定向),一般用于服务器的负载均衡,当前服务器处理不了,我把当前请求临时交给其他的服务器处理(一般图片请求经常出现302,很多公司都有单独的图片服务器)
304
:Not Modified 从浏览器缓存中获取数据,把一些不经常更新的文件或者内容缓存到浏览器中,下一次从缓存中获取,减轻服务器压力,也提高页面加载速度
以4开头的,一般都是失败,而且客户端的问题偏大
400
:请求参数错误
401
:无权限访问
404
:访问路径不存在
以5开头的,一般都是失败,而且服务器的问题偏大
500
:Internal Server Error 未知的服务器错误
503
:Service Unavailable 服务器出超负载
AJAX中其他常用的属性和方法
面试题:AJAX中总共支持几个方法?
let xhr=new XMLHttpRequest();
console.dir(xhr);
[属性]
readyState
:存储的是当前AJAX的状态码response/responseText/responseXML
:都是用来接收服务器返回的响应主体中的内容,只是根军服务器返回内容的格式不一样,我们使用不同的属性接收即可responseText
:是最常用的,接收到的结果是字符串格式的(一般服务器返回的数据都是JSON格式字符串)reseponseXML
:偶尔用到,如果服务器端返回的是XML文档数据,我们需要使用这个属性接收status
:记录了服务器端返回的HTTP状态码statusText
:对返回状态码的描述timeout
:设置当前AJAX请求的超时时间,假设我们设置时间为3000ms,从AJAX请求发送开始,3秒后相应主体内容还没有返回,浏览器会把当前AJAX请求任务轻质断开
[方法]
abort()
:强制中断AJAX请求getAllResponseHeaders()
:获取全部的响应头信息(获取的结果是一堆字符串文本)getResponseHeaders(key)
:获取指定属性名的响应头信息,例如:getResponseHeaders(‘date’)获取响应头中存储的服务器的时间open()
:打开一个URL地址overrideMimeType()
:重写数据的MIME类型send()
:发送AJAX请求(括号中书写的内容是客户端基于请求主体把信息传递给服务器)sendRequestHeader(key,value)
:设置请求头信息(可以是设置的自定义请求头信息)
[事件]
onabort
:当AJAX被中断请求触发这个事件onreadystatechange
:AJAX状态发生改变,会触发这个事件ontimeout
:当AJAX请求超时时,会触发这个事件
例子:
let xhr=new XMLHttpRequest();
xhr.open('get','temp.xml?_='+Math.random(),true);
//设置的请求头 内容不是一个有效的值(请求头部的内容不得出现中文汉字)
//设置请求头信息必须在OPEN之后和SEND之前
xhr.setRequestHeader('aaa','xxx');
xhr.timeout=5000;
xhr.ontimeout=()=>{
console.log('当前请求已经超时');
xhr.abort();
};
xhr.onreadystatechange=()=>{
let {readyState:state,status}=xhr;
//说明请求数据成功了
if(!/^(2|3)\d{2}$/.test(status)) return;
//在状态为2时就可以获取响应头信息
if(state==2){
let headerAll=xhr.getAllResponseHeaders(),
serverDate=xhr.getResponseHeader('date');
console.log(headerAll,new Date(serverDate));//获取的服务器时间是格林尼治时间(相比于北京时间差了8小时),通过new Date可以装换为北京时间
//在状态为4的时候响应主体内容就已经回来了
if(state===4){
let valueText=xhr.responseText,
valueXML=xhr.responseXML;
console.log(valueText,valueXML)
}
}
};
xhr.send('name=mary&age=12');
JS中常用的编码解码方法
正常的编码解码(非加密)
1、escape/unescape:主要就是把中文汉字进行编码和解码的(一般只有js语言支持,也经常应用于前端页面通信时候的中文汉字编码)
2、encodeURI/decodeURI:基本上所有的编程语言都支持
3、encodeURIComponent/decodeURIComponent:和第二种方式非常的类似,区别在于
需求:我们URL问号传递参数的时候,我们传递的参数值还是一个URL或者包含很多特殊的字符,此时为了不影响主要的URL,我们需要把传递的参数值进行编码,使用encodeURI不能编码一些特殊字符,所以只能使用encodeURIComponent处理
let str='http://www.baidu.com/?',
obj={
name:'小明',
age:10,
url:'http://www.qq.com/?lx=1'
};
//把obj中的每一项属性名和属性值拼接到URL的末尾(问号传参方式)
for(let key in obj){
//不能使用encodeURL,必须使用encodeURIComponent,原因是encodeURL不能编码特殊字符
str+=`${key}=${encodeURIComponent(obj[key])}&`;
}
console.log(str.replace(/&$/g),'');
//后期获取URL参数的时候,我们把获取的值在一次的解码即可
String.prototype.myQueryUrlParameter=function myQueryUrlParameter(){
let reg=/[?&]([^?&=]+)(?:=([^?&=]*))?/g,
obj={};
this.replace(reg,(...arg)=>{
let [,key,value]=arg;
obj[key]=decodeURIComponet(value);//此处获取的时候可以进行解码
})
return obj;
}
也可以通过加密的方法进行编码解码
1、可逆转加密(一般都是自己团队设置的规则)
2、不可逆转加密(一般都是基于MD5加密完成的,可能会把MD5加密后的结果二次加密)
AJAX中的同步和异步
ajax这个任务:发送请求接收到响应主体内容(完成一个完整的HTTP事务)
xhr.send():任务开始
xhr.readyState===4:任务结束
let xhr=new XMLHttpRequest();
xhr.open('get','temp.json',false);
xhr,onreadystatechange=()=>{
console.log(xhr.readystate);
}
xhr,send();
//只输出一次结果,是4
let xhr=new XMLHttpRequest();
xhr.open('get','temp.json',false);
xhr,send();//=>[同步]开始发送AJAX请求,开启AJAX任务,在任务没有完成之前,什么事情都做不了(下面绑定时间也做不了)=>LOADING=>当readyState===4的时候,AJAX任务完成,开始执行下面的操作
//readState===4
xhr,onreadystatechange=()=>{
console.log(xhr.readystate);
}
//绑定方法之前状态已经为4了,此时AJAX的状态不会再改变成其他值,所以事件永远不会被触发,一次都妹妹执行方法(使用ajax同步编程,不要把SEND放在事件监听前,这样我们无法在绑定的方法中获取到响应主体的内容)
let xhr=new XMLHttpRequest();
xhr.open('get','temp.json');
xhr,onreadystatechange=()=>{
console.log(xhr.readystate);
}
xhr,send();
//输出是3次,结果是 2 3 4
let xhr=new XMLHttpRequest();
xhr.open('get','temp.json');
xhr,send();
xhr,onreadystatechange=()=>{
console.log(xhr.readystate);
}
//输出是3次,结果是 2 3 4
let xhr=new XMLHttpRequest();
xhr,onreadystatechange=()=>{
console.log(xhr.readystate);
}
xhr.open('get','temp.json');
xhr,send();
//输出是4次,1 2 3 4
let xhr=new XMLHttpRequest();
//xhr.readyState===0
xhr,onreadystatechange=()=>{
console.log(xhr.readystate);
}
xhr.open('get','temp.json',false);
//xhr.readyState===1 同步中AJAX特殊处理的一件事:执行OPEN状态为1,会主动把之前监听的方法执行一次,然后再去执行SEND.
xhr,send();
//xhr.readyState===4 AJAX任务结束,主任务队列完成
//输出是2次,1 4