Ajax
英文全称为 Asynchronous JavaScript + XML
,翻译过来就是 异步JavaScript和XML。
Ajax 最重要的特性就是可以局部刷新页面。
-
Ajax 是一种代表异步 JavaScript + XML 的模型(技术合集),所以 Fetch 也是 Ajax 的一个子集
-
在之前,我们常说的 Ajax 默认是指以 XHR 为核心的技术合集,而在有了 Fetch 之后,Ajax 不再单单指 XHR 了,我们将以 XHR 为核心的 Ajax 技术称作传统 Ajax。
-
Axios 属于传统 Ajax(XHR)的子集,因为它是基于 XHR 进行的封装。
xhr
xhr是利用 XMLHttpRequest 模块实现的最传统的网络请求
实现步骤:
- 创建xhr实例 const xhr = new XMLHttpRequest()
- 设置请求方法和地址 xhr.open(‘GET’, url)
- 如果是POST请求 ,告诉后端发送的参数是什么形式的xhr.setRequestHeader(‘content-type’,’application/json’)
- 发送请求 xhr.send()
- 注册回调
const xhr = new XMLHttpRequest()
xhr.open('POST',url)
xhr.setRequestHeader('content-type','application/x-www-form- urlencoded')
xhr.send(params)
xhr.responseType = 'json' xhr.addEventListener('readystatechange',()=>{ if(xhr.readyState !==4) return
if(xhr.status >= 200 && xhr.status <300){
console.log(xhr.response)
}else{
console.log('错误')
}
readyState ==> 请求状态码 , xhr的状态
- 0 表示请求未初始化,还没有调用 open()
- 1 表示服务器已建立 但是还没有 调用send()
- 2 请求已接收, 正在处理中
- 3 请求处理中 已经有部分数据响应了,没有全部完成
- 4 请求已完成 (全部数据已经下载完了)
Axios
Axios 是一个基于 promise 封装的网络请求库,基于 XHR 进行二次封装形成的工具库,在项目中直接安装使用
Axios 是一个基于 Promise 网络请求库,作用于 Node.js 和浏览器中。在服务端它使用原生 Node.js http 模块,而在客户端则使用 XMLHttpRequest。
axions({
method:"POST",
data:{}, // 直接绑定 data (fetch 需要转换格式绑定在 body 上)
params: {}, // params 会绑定在 url 查询上
headers:{
"content-type":"application/json" // headers 与 fetch ⼀致,但是默认值是 “application/json”
}
}).then(res=>{
// res.data 返回结果,res.status 返回状态
// 没有第⼆段 then
})
//get请求
axios({url})
.then(res => console.log(res))
//post
axios({
method:"POST",
data:{},
params: {加载地址后面的},
headers:{"content-type":"application/json" }
}).then(res => console.log(res.data))
fetch
口诀:fetch 两段 then,错误全 catch
Fetch 是一个现代的概念, 等同于 XMLHttpRequest。它提供了许多与 XMLHttpRequest 相同的功能,但被设计成更具可扩展性和高效性。
Fetch 的核心在于对 HTTP 接口的抽象,包括 Request、Response、Headers 和 Body,以及用于初始化异步请求的 global fetch
。得益于 JavaScript 实现的这些抽象好的 HTTP 模块,其他接口能够很方便的使用这些功能。
Fetch 还利用到了请求的异步特性——它是基于 Promise 的。
fetch()
方法必须接受一个参数——资源的路径。无论请求成功与否,它都返回一个 Promise 对象
fetch(url,{
method:"post",
headers:{'content-type':"application/json"},
body:JSON.stringify(params)
}).then(res => res.json())
.then(res => console.log(res))
.catch(err => console.log(err))
//get请求
fetch('http://ajax-api.itheima.net/api/news')
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.log(err))
//post请求
fetch('http://ajax-api.itheima.net/api/login',{
method:"post",
headers:{'content-type':"application/json"},
body:JSON.stringify(params)
}).then(res => res.json())
.then(res => console.log(res))
.catch(err => console.log(err))
promise
上面请求都是基于promise,因为请求都是异步运行的,所以promise是用来做异步处理的,下面来说说promise是什么
推导promise的进化 下面代码需要事件循环基础,不了解可以点击这里查看
1.闭包
let a = { value: 1 };
let value = a.value;
setTimeout(() => {
console.log(value);
a.value = 2;
}, 1000);
setTimeout(() => {
console.log(value); // 1
}, 1000);
2.函数闭包,专门为了异步存在
// 值的引用:改变了栈里面的值,引用的是同一个值,值改变其他引用也会变
// 第一种情况: let a = 1;
setTimeout(() => {
console.log(a); //1
a = 2;
}, 1000);
setTimeout(() => {
console.log(a); //1
}, 500);
// 第二种情况: let a = 1;
setTimeout(() => {
console.log(a); //1
a = 2;
}, 1000);
setTimeout(() => {
console.log(a); //2
}, 1000);
// 记住了特定时刻的a值
// 对象的引用:对象里面的属性值改变,不会影响其他的引用,这里的value2和a存储在不同的空间中,互不影响
const a = { value: 1 };
const value2 = a.value; // a.value 是右值
// const {value2} = a // 解构赋值
setTimeout(() => {
console.log(value2); //1
a.value = 2;
}, 1000);
setTimeout(() => {
console.log(value2); //1
}, 2000);
3.异步回调
函数当作参数传递(回调),在异步结果中调用(异步回调),因为函数作用域存在,所以回调在异步中调用时,可以拿到最新的引用
let a = 1;
function wait(cb) {
setTimeout(() => {
cb()
},1000);
}
function callback() {
console.log(a); //2
}
wait(callback);
a = 2;
4.回调地狱(promise最重要的作用)
回调地狱出现的问题:
- 取值引用问题
- 常量冲突
- 变量遮蔽
- 大椎形代码
// 嵌套太多,分不清楚引用的是谁了,后面的变量会遮蔽前面的值
const a = { value: 1 };
const { value } = a;
wait(() => {
// 常量冲突
const b = 1;
console.log(1);
wait((res) => {
console.log(2);
// 变量遮蔽
wait((res) => {
console.log(res);
console.log(3);
b = 2;
});
});
});
5.promise 用来解决回调地狱的 ( 让异步任务进行同步处理)
function wait(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`等待${n}毫秒`); // .then 的回调,在这里跑
}, n);
// 然后 一段时间以后
});
}
wait(1000).then((res) => {
console.log(res);
});
6.promise 链式调用 就是(promise.then())
思想:等待一段时间,干一件事,再等待一段时间,再干一件事 …
function wait(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`等待${n}毫秒`); // .then 的回调,在这里跑
}, n);
// 然后 一段时间以后
});
}
wait(1000)
.then((res) => {
console.log(res);
// 当 .then 返回的值是 promise,下一个.then(的参数)是promise的resolve
return wait(1000);
})
.then((res) => {
console.log(res);
// 当 .then 返回的值,不是 promise 的时候,下一个 .then 就是这个值
return "立即执行";
})
.then((res) => {
console.log(res);
});
async/await
promise的语法糖 ⽤同步的⽅式,写异步代码
async function asyncFunction() {
const res1 = await wait(1000);
console.log(res1);
const res2 = await wait(1000);
console.log(res2);
const res3 = await wait(1000);
console.log(res3); }
// 等同于
function promiseFuction() {
wait(1000)
.then((res1) => {
console.log(res1);
return wait(1000);
})
.then((res2) => {
console.log(res2);
return wait(1000);
})
.then((res3) => {
console.log(res3);
});
}
promise拓展
获取⼀个 Promise 列表中,所有 Promise resolve 的值
Promise.all([promise1, promise2]).then((res) => {
const [result1, result2] = res;
});
Promise.race()
获取⼀个 Promise 列表中,第⼀个 resolve 的值
function wait(n) {
return new Promise((res) => {
setTimeout(() => {
console.log(1);
res(`等待了${n}毫秒`);
console.log(2);
}, n);
});
}
Promise.race([wait(1000), wait(500), wait(3000)]).then((res) => {
console.log("Promise.race", res); //等待了500毫秒
});