Fetch API 提供了一个 JavaScript接口,用于访问和操纵 HTTP 管道的部分,例如请求和响应。它还提供了一个全局 fetch()方法,该方法提供了一种简单,合乎逻辑的方式来跨网络异步获取资源。javascript
fetch()
必须接受一个参数---路径。不管请求成功与否,它都返回一个 Promise 对象,resolve 对应请求的 Response
。另外你还能够设置第二个参数(可选的参数)options(经常使用配置以下,具体详情参见 Request
)。java
options={
// 请求方式 GET,POST,等
method: "GET",
// 请求头headers
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=UTF-8',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
// omit: 从不发送cookies.
// same-origin 只有当URL与响应脚本同源才发送 cookies
// include 老是发送请求资源域在本地的 cookies 验证信息
credentials: 'include',
//包含请求的模式 (例如: cors, no-cors, same-origin, navigate)
//no-cors: 经常使用于跨域请求不带CORS响应头场景
//cors表示同域和带有CORS响应头的跨域下可请求成功. 其余请求将被拒绝
mode: 'cors',
//包含请求的缓存模式 (例如: default, reload, no-cache).具体参数见下面(cache参数)
cache: 'default'
}
复制代码
cache 表示如何处理缓存, 遵照 http 规范, 拥有以下几种值:json
这是一个比较基本的案例,这里为了看的清楚,没有处理 catch 问题 。segmentfault
var url = 'https://zhidao.baidu.com/question/api/hotword?pn=1561&rn=5&t=1551165472017';
fetch(url).then(function(response) {
return response;
}).then(function(data) {
console.log(data);
})
复制代码
能够本身动手把这个代码直接贴到控制台中 , 这里为了防止同源策略,而且看到更详细的数据咱们最好在 https://zhidao.baidu.com 内的控制台中输入。若是在其余的页面咱们应该在 fetch 方法的第二个参数中加上{ mode: "no-cors" }。为了看的更加清楚,我贴出这两种状况的打印结果,以下所示:api
在 https://zhidao.baidu.com 网页控制台输入的地址跨域
在其余网页控制台输入的地址promise
咱们会发现两个打印结果基本不一样,首先跨域打印的结果中不少数据都是空的,另外咱们也发现其中 type 也不相同,这里介绍下 response.type。浏览器
fetch请求的响应类型( response.type )为以下三种之一:缓存
fetch
设了{mode='no-cors'}
表示不垮域,能够请求成功,但拿不到服务器返回数据服务器
看到这里,心急的同窗会发现,其实如今数据仍是没有拿到,咱们仅仅只是拿到了个 Response 对象。那么如何拿到数据呢?
瞧好:
var url = 'https://zhidao.baidu.com/question/api/hotword?pn=1561&rn=5&t=1551165472017';
fetch(url).then(function(response) {
//经过 response 原型上的 json 方法拿到数据,在返回出去
return response.json();
}).then(function(data) {
// 接收到 data 打印出来
console.log(data);
})
复制代码
经过 response 原型上的 json 方法拿到数据,在返回出去。response 原型打印以下:
这里要注意的是 response .json / response.text 方法只能使用一个而且只能使用一次,同时使用两个,或则使用两次都会报以下错误:
Uncaught (in promise) TypeError: Failed to execute 'json' on 'Response': body stream is locked
为何不能使用两次?
数据流只能读取一次,一旦读取,数据流变空,再次读取会报错。可使用 response.clone() 复制一个副本。
为何只能读取一次?
答案还在查寻中,同时也但愿知道的读者可以指点一下。
上面的写法,看起来有回调,又有链式调用,咱们试着换个新写法,这里使用 async/await 来实现:
var url = 'https://zhidao.baidu.com/question/api/hotword?pn=1&rn=5&t=1551191647420';
let getData = async () => {
let response = await fetch(url);
let data = response.json();
console.log(data)
}
复制代码
打印 data 以下:
这里 data 是一个 Promise 对象,因为他的内部变量[[PromiseValue]]在外部没法获得,只能在 then 中获取,因此在后面加上 then 获取 data
let response = await fetch(url);
let data = response.json();
data.then((res)=>{
console.log(res)
})
// 搞定 res 就是咱们要的数据拉
复制代码
咱们经过 fetch 来作个简易的 request 封装,顺便把 options 再回顾一遍,不少配置在实际中多是不须要的,都有默认配置(options 的默认配置在下面括号中)。
function request(url, data = {}) {
// options配置的默认选项在括号中
return fetch(url, {
method: "POST", //(GET), POST, PUT, DELETE, etc
mode: "cors", // (same-origin), no-cors, cors
cache: "no-cache", // (default), no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", //(same-origin), include, omit
headers: {
"Content-Type": "application/json",
// "Content-Type": "application/x-www-form-urlencoded",
},
redirect: "follow", //(follow), manual, error
referrer: "no-referrer", //(client), no-referrer
body: JSON.stringify(data), // 这里格式要与 "Content-Type" 同步
})
.then(response => response.json());
}
复制代码
初次写帖,若有错误或不严谨的地方,请务必给予指正,谢谢
参考: