共计 2794 个字符,预计需要花费 7 分钟才能阅读完成。
欢迎访问我的个人博客:http://www.xiaolongwu.cn
基本知识
1. Ajax 是什么?
答:Ajax 是一种可以在浏览器和服务器之间使用异步数据传输(HTTP 请求)的技术。使用它可以让页面请求少量的数据,而不用刷新整个页面。而传统的页面(不使用 Ajax)要刷新部分内容,必须重载整个网页页面。
2. Ajax 基于什么?
答:它基于的是 XMLHttpRequest(XHR)。这是一个比较粗糙的 API,不符合关注分离的设计原则(Separation of Concerns),配置和使用都不是那么友好。
3. Ajax 的库?
答:基于上面的原因,各种 ajax 库引用而生,然而最有名的就是 jQuery 的 API 中的 $.ajax()。$.ajax() 它的一个优势异步操作,但 jQuery 的异步操作是基于事件的异步模型,没有 promise 那么友好。
4. fetch 产生的背景?
答:综合上面所讲的各种因素,fetch 这个 api 应运而生,它和 XMLHttpRequest 都是浏览器 window 对象的原生 api。但好用归好用,它存在着一些问题(这个问题下面详讲,并讲解相对应的解决方案),再加上兼容性问题(ie11 以下压根不支持),所以很多开发者使用了 axios 这个第三方库。
5. 支持 promise 的库(axios)?
答:axios 这个库现在是一个比较通用的行业解决方案,axios 流行开来的一个原因是 promise,另一个原因是基于数据操作的库的流行(vue.js, angular.js, react.js 等),而传统的 jQuery 是基于 dom 操作的库。但它也存在着缺陷,就是我们使用前,要保证这个库已经被引入。
其实,就我个人而言,我还是比较喜欢使用 fetch 的。在开发中遇到兼容性的问题,只需要同构 fetch 即可,而不需要额外的引入一个库。下面就重点说一下 fetch。
fetch 的使用
fetch(url, options)
.then(response => console.log(responese))
.catch(err => console.log(err))
url:请求的地址
options:请求的相关参数配置
response:请求返回的对象
then:正常返回数据
catch:返回异常
请求参数配置 options 详情可参考 MDN fetch 我在这里就不再赘述
fetch 存在的问题及解决方案
fetch 得到数据你需要两个步骤
fetch(‘https://api.github.com/users’)
.then(res => {
console.log(res)
return res.text()
})
.then(data => {
console.log(data)
})
fetch 的使用需要浏览器支持 promise,fetch 的返回值也是一个 promise 对象;
通过上面的代码,可以发现直接打印返回的 Response 对象中压根就没有数据,要想获取到所需的数据,必须经一个中间的方法 response.text()(fetch 提供了 5 中方法),如下:
// 具体功能请自行查阅
arrayBuffer()
blob()
json()
text()
formData()
而 fetch 的封装库 axios 解决了这个问题,使用起来就要方便的多,它返回的 Response 对象中却有数据,在 data 属性内。参考代码如下:
axios.get(‘https://api.github.com/users’)
.then(res => console.log(res));
fetch 的请求默认是不带 cookie
解决这个问题,需要在 options 中配置 {credentials: ‘include’}
并非所有的请求错误都会 reject
也就是说 catch 方法并不能捕获所有的错误,当错误可以用一个状态码(如:404,500 等)的形式表示时,fetch 返回的 Promise 不会拥有 reject,只有当网络故障或请求被阻止时 catch 才有效。
解决这个问题,我们可判断 Response 对象中的 ok 是否为 true,如果不是,用 Promise 手动添加一个 reject 即可。参考代码如下:
fetch(‘https://api.github.com/usrs’)
.then(res => {
if (res.ok) {
return res.text()
} else {
return Promise.reject(‘ 请求失败 ’)
}
})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
})
当然,如果是用 axios 库就不需要考虑这个问题,因为 axios 已经为我们封装好了;
fetch 和 async、await 在实际中一起使用
async 和 await 是 es7 的 api,在实际开发中加入一些 polyfill 库,比如最流行的的 babel,我们就可以使用它们了;
如果你还不了解它们,请跳转至:用 async/await 来处理异步
在实际中我们会经常遇到异步嵌套的问题,比如:
fetch(‘https://api.github.com/usrs’)
.then(res => {
if (res.ok) {
return res.text()
} else {
return Promise.reject(‘ 请求失败 ’)
}
})
.then(data => {
let url = data.url
fetch(url)
.then(res => {
if (res.ok) {
return res.text()
} else {
return Promise.reject(‘ 请求失败 ’)
}
})
.then(data => {
console.log(data)
})
})
.catch(err => {
console.log(err)
})
上面就是在收到相应之后再发起一个请求,这样的代码是不是看着很难受;
下面我们来用 async 和 await 改一下,感受一下用同步的方式写异步的感觉:
// 封装 aa
async function aa() {
try {
let res = await fetch(‘https://api.github.com/usrs’)
let data = await res.text()
let url = data.url
let res1 = await fetch(url)
let data1 = await res1.text()
console.log(data)
} catch(e) {
console.log(“error”, e)
}
}
// 调用 aa
aa()
看看上面的代码是不是舒服多了,也简单多了;
github 资源地址:js 基础进阶 – 从 ajax 到 fetch 的理解
我的 CSDN 博客地址:https://blog.csdn.net/wxl1555
如果您对我的博客内容有疑惑或质疑的地方,请在下方评论区留言,或邮件给我,共同学习进步。
邮箱:wuxiaolong802@163.com