网络请求与远程资源(写给前端小白的理解笔记)

web自诞生以来 一直都是传统的单机等待的模式,即浏览器页面向服务器请求数据时,返回的是整个页面,整个页面都会刷新,当我们只需要请求部分数据时,返回整个页面会造成网络资源的占用.(我只要换个套餐里的饮料,店里只能把整个套餐都换下去,占用公共资源了dbq)

这个时候XHR对象 这一关键技术出现了(是XHR,我们有救了!)

XHR对象为 发送服务请求和获取响应 提供了合理的接口,这个接口可以实现 异步从服务器获取额外数据.在不刷新整个页面的情况下,从服务器获取数据.(XHR对象的api 可以让就餐的我们不再干等着换整个套餐,而是可以一边吃 一边帮我们更换饮料)

(API(Application Programming Interface)是一种接口。‌ API是一组预先定义的函数或协议,旨在提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而无需访问源码或理解内部工作机制的细节。‌)

但是XHR对象的api不好用,后来Fetch api 替代了它.

1.XMLHttpRequest即XHR对象

所有现代浏览器都通过 XMLHttpRequest构造函数原生支持XHR对象.

let xhr = new XMLHttpRequest();

1.1 使用XHR

xhr.open(请求类型,请求URL,是否异步) 来准备发送请求

xhr.send(请求体发送数据) 将请求发送到服务器

收到响应后 XHR对象的属性status responseText responseXML 等 会被填充上数据.

收到响应后 首先检查status状态码,查看响应状态,以此来确定下一步执行什么操作. responseText始终保存响应体.

浏览器向服务器发送请求,通常都是通过HTTP或HTTPS协议完成的,特殊情况下用其他的协议,如浏览器与服务器之间实时双向通信,会将HTTP协议升级为WebSocket协议.

HTTP 是HyperText Transfer Protocol的缩写,翻译为 超文本传输协议

1.2HTTP头部

每个HTTP请求和响应都会携带一些头部字段,这些字段对开发者可能有用.

XHR请求通常也是通过HTTP协议发送请求.

默认情况下,XHR请求会发送以下头部字段.

    • Accept: 浏览器可以处理的内容类型
    • Accept-Charset: 浏览器可以显示的字符集
    • Accept-Encoding 浏览器可以处理的压缩编码类型
    • Accept-Language 浏览器使用的语言
    • Cookie 页面中设置的cookie(HTTP协议本身是无状态的 即每次请求服务器都不会记得你是谁,而cookie就像一张小纸条用来记住你在网站上的一些信息比如 "我是已经登陆过的小明""我选了黑暗模式 购物车里加了点好东西 ""我看了哪些内容 点了哪些广告" 总的来说 cookie就是帮助网站记住用户的身份和习惯)
    • Host 发送请求的页面所在的域 (Host主机 指的是连接到网络中的任何设备,比如电脑 手机 打印机 服务器 只要能与其他设备通信 就可以称为主机Host. )
    • Referer 发送请求的页面的URI (URL 英文全称为(Uniform Resource Locator,URL),中文叫统一资源定位器。URI(统一资源标识符)是一个用于标识互联网资源名称的字符串。打个简单的比喻,如果用URI和URL来表述我们自己,那么URI就是我们的身份证号码,URL就是我们身份证上的家庭住址,通过身份证号(URI)肯定能找到我,但是你通过我的住址(URL)那就不一定能找到我了哦)
    • User-Agent: 浏览器的用户代理字符串

(HTTP请求头部 类似于 我们在点菜的时候 告诉服务员 我是谁 我现在在哪里 我可以吃哪些菜,响应我请求的时候 最好按照这些信息来 )

1.3GET请求

最常用的请求方法就是GET请求, 用于向服务器查询某些信息.

必要时,需要在get请求的URL后面添加查询字符串参数.(三分钟之内 我要拿到""名字叫小帅""的所有信息! renlei.php?name=xiaoshuai&look=handsome)

对于XHR而言,查询字符串必须正确编码侯 添加到URL后面,然后再传给open方法.

1.4 POST请求

第二常用的请求,用来向服务器发送应该保存的数据.

每个POST请求都应该在请求体中 携带提交的数据. POST请求体中 可以包含非常多的数据,而且数据可以是任意的格式.

1.5 XHR Level2

XHR Level2进一步发展了XHR对象.

①新增了FormData类型,便于表单的序列化. let data = new FormData();

②XHR对象新增了timeout属性,用来表示 发送请求后等待多少毫秒,如果响应不成功,就中断请求.

xhr.timeout =1000// 设置1s超时.

③引入overrideMimeType()方法.用来重写XHR响应的MIME类型.(override是覆盖的意思 MIME类型(Multipurpose Internet Mail Extensions)是一种用于标识电子邮件和网页内容的类型和格式的标准。‌MIME类型由两部分组成:类型和子类型,例如“text/html”表示HTML文档。MIME类型在HTTP协议中非常重要,帮助浏览器理解服务器返回的内容,从而正确显示给用户,) 如果服务器实际发送的是XML数据,而响应头设置的MIME类型是text/plain即纯文本,那么会导致responseXML属性值为null(responseXML属性的内心OS: 你说你是纯文本,不需要我来去接收XML啊??) MIME类型可以被overrideMimeType方法改变,改为XML类型.

xhr.overrideMImeType("text/XML")

2 进度事件(略)

3.跨源资源共享

通过XHR进行Ajax通信(不刷新页面的情况下从服务器获取数据)的一个主要限制是跨源安全策略.

默认情况下, XHR只能访问 与发起请求的页面在同一域内的资源.

这个安全限制 可以防止某些恶意的行为.不过浏览器也需要支持合法跨源访问的能力.(只吃公司食堂确实安全,但是也需要去其他餐厅换换口味)

跨源资源共享(CORS,Cross-Origin Resource Sharing ) 定义了浏览器与服务器如何进行跨源通信.

CORS 背后的基本思路就是 使用自定义的HTTP头部允许浏览器和服务器相互了解 以确定请求或响应 应该成功还是失败.

对于简单的请求如post或get请求 --没有自定义头部 并且请求体是text/plain类型(纯文本类型) 这样的请求在发送时,会有一个额外的头部叫Origin (Origin头部,包含发送请求的页面的源即协议 域名 端口) 以便服务器确定 是否为其提供响应 ( 我是你七大姑的八大姨的远方表哥的亲弟弟的儿子 过来吃顿饭可以吧?)

Origin: http://www.qidagubadayi.net

如果服务器决定 响应请求,那么应该发送Access-Control-Allow-Origin 头部,包含相同的源.如果资源是对所有请求公开的,那么就包含" * ". (Access通道的意思)

Access-Control-Allow-Origin: http://www.qidagubadayi.net
注意 如果没有这个头部,或者头部有这个头部 但是源不匹配,则表明不会响应浏览器请求.
只有有这个头部 并且源可以匹配的情况下,浏览器会处理这个请求.

如何使用CORS??

现代浏览器请求通过XMLHttpRequest对象原生支持CORS.在尝试访问不同源的资源时,这个行为会被自动触发.

要向不同域的源 发送请求,可以使用标准XHR对象 并给open()方法传入一个绝对URL 如下

xhr.open("get","http://www.somewhere-else.com/pages/",true);

跨源的xhr对象 允许访问status和statuesText属性 (status是HTTP响应状态码 stauesText是HTTP响应状态码对应的文本信息 200对应"OK" 404对应"Not Found"),也允许同步请求,但是为了安全考虑, 跨域XHR对象也施加了一些额外的限制.( 对跨域的非亲非故的对象多一些警惕 多一些限制)

  • 不能使用setRequestHeader() 设置自定义头部
  • 不能发送和接受cookie
  • getAllResponseHeaders() 方法始终返回空字符串.

因为无论同域还是跨域请求,都使用同一个接口 xhr.open() 所有最好区分一下,在访问本地资源时使用相对路径,在访问远程资源时使用绝对URL.这样可以更明确区分使用场景,避免出现访问本地资源时 出现 头部或cookie信息 访问受限的问题.

4.替代性跨源技术(略)

5.Fetch API(※)

Fetch API能够执行XMLHttpRequest对象的所有任务,并且更容易使用 接口也更现代化,能够在web工作线程等现代web工具中使用.

XHR可以选择异步,而FetchAPI必须是异步.

Fetch标准定义 请求、响应,以及绑定二者的流程。

Fetch API 本身是使用JS请求资源的优秀工具, 同时这个API也能够应用在服务线程中,提供拦截、重定向和修改通过fetch()生成的请求接口。

5.1 基本用法

fetch()方法是暴露在全局作用域中的.调用这个方法,浏览器就会向给定URL发送请求.

1.分派请求

fetch() 只有一个必须得参数input.这个参数大多数是要获取资源的URL.(同域请求使用相对路径,跨域请求使用绝对路径)

fetch 方法返回一个promise.

请求完成,资源可用时,promise会解决为一个Response对象即resolve(response). Response对象是API的封装,可以通过它取得相应的资源. 获取资源也要使用response对象的属性和方法, 掌握响应的情况 并将负载转换有用的形式

fetch('bar.txt')
  .then((response) => {
    console.log(response);
  });
//Response { type:"basic" ,url:...}

2.读取响应

读取响应内容最简单的方式是获取纯文本格式的内容,用到text()方法.

text()方法返回 一个promise,会解决为取得资源的完整内容即resolve(获取的资源的完成内容)

fetch('bar.text')
  .then( (response) => response.text() )
  .then( (data) => console.log(data) );
  //bar.text的内容

以上都是获取成功的情况,以及执行的操作

3.处理状态码和请求失败

fetch API支持通过Response的status和statusText属性检查响应状态

成功获取响应的请求 --状态码为200

请求不存在的资源--404

请求的URL如果抛出服务器错误--500

可以显式地设置fetch() 在遇到重定向时的行为.

fetch请求后,只要服务器返回了响应,fetch方法返回的promise都会解决即resolve(response); 表示系统级网络协议已经成功完成消息的一次往返传输. 在处理响应时 可以找到真正"成功"的请求.通常状态码为200时 会被认为成功了.即response.status为200.

因为服务器没有响应而导致浏览器超时,这样fetch()失败 promise被拒绝即 reject(error) 还有违反CORS等原因都会导致promise被拒绝.

可以通过response对象的url属性 检查通过fetch()发送请求时 完整的URL

4.自定义选项

fetch()方法 如果参数只使用URL时, 会发送GET请求,只包含最低限度的请求头.

如果要进一步配置如何发送请求,需要传入可选的第二个参数 即init对象.init对象按照键/值进行填充.

method --用于指定HTTP请求方法.默认为GET,可选值 GET POST PUT等

body--指定使用请求体时 请求体的内容 必须是Blob、FormData、String等等的实例。

5.2 常见Fetch请求模式

与XHR一样,fetch既可以post发送数据 也可以 get收取数据。

使用init对象参数,可以配置fetch在请求体中发送各种序列化的数据。

5.3 Headers 对象

Headers对象是所有 外发请求和入站响应 头部的容器.

每个外发的Request实例 都包含一个空的Headers实例 可以通过Request.prototype.headers访问.

每个入站的Response实例 也可以通过Response.prototype.headers访问包含响应头部的Headers对象.

5.4 Request对象

request对象是获取资源请求的接口.这个接口暴露了请求的相关信息.也暴露了使用请求体的不同方式.

5.5 Response对象

response对象是获取资源响应的接口.这个接口暴露了响应 相关的信息,也暴露了使用响应体的不同方式.

5.6 Request Response 及 Body混入

Request和Response都使用了Fetch API的body混入.来实现两者承担有效载荷的能力.

这个混入为两个类型提供了只读的body属性 只读的bodyUsed布尔值 和一组方法. 用于从流中读取内容并将结果转换成JavaScript对象类型.

( 在使用 fetch API 发起请求时,body 是用来存放请求主体数据的字段,通常会用在 POST、PUT 等需要传递数据的 HTTP 方法中。而“混入”的意思是,在构造请求时,把一些额外的数据“添加”到 body 中,形成一个包含多项内容的请求主体。 假如你点外卖,需要告诉店家两部分信息:1. 你要点的菜(必要信息)。2. 你的特殊要求,比如“少辣”、“加餐具”(额外信息)。“混入”就好比在点菜信息里,把你的特殊要求也写进去,合在一起发给店家。)

-----------------

本文中主要内容来自于《 JS高级程序设计4.0 》添加了一些个人理解以及ai辅助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值