Ajax、Axios、Fetch的区别
Ajax
传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,以下面登录请求为例,如果多个请求之间有先后关系的话,就会出现回调地狱问题。
$.ajax({
url: 'http://127.0.0.1:8888/user/login',
method: 'post',
data: {
username: 'zhansan',
password: '123456'
},
success(res) {
if (res.code === 0) {
// 登录成功 获取列表信息
$.ajax({
url: 'http://127.0.0.1:8888/user/list',
method: 'get',
success(res) {
console.log(res);
...
...
}
})
}
}
})
Axios
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范。配合asyns,await相对于JQajax最大的有点就是解决了回调地狱问题
(async function () {
let result = await axios.post('/user/login', {
username: 'admin',
password: '123456'
});
result = await axios.get('/user/list');
console.log(result);
...
...
})();
Fetch
fetch是ES6出的基于promise设计的API,需要注意的是,fetch不是对ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
(async function () {
let result = await fetch('/user/login', {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: {
username: 'admin',
password: '123456'
}
}).then(res => {
return res.json();
});
result = await fetch('/user/list').then(res => {
return res.json();
});
console.log(result);
...
...
})();
串行与并行
串行:请求是异步的,需要等待上一个请求结果成功,才会执行下一个请求。
并行:同时发送多个请求,待所有请求都成功才会去执行下一步操作
HTTP请求可以同时进行,但是JS是单线程,代码是逐行解析的。
Promise.all并发限制和async-pool的应用
const delay = function delay(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(time);
}, time);
});
};
// tasks中的每一项都是一个请求任务
let tasks = [delay(1000), delay(100), delay(3000), delay(2300), delay(900), delay(1500)]
console.time('时间')
Promise.all(tasks).then(results => {
console.log(results);
console.timeEnd('时间')
});
Promise.all所有的请求队列同时并发进行,只有所有的请求全部成功才会一次性将结果返回,所以总用时一定是最久的那个(长板效应)
let data = [];
asyncPool(2, tasks, (task, next) => {
task.then(res => {
data.push(res);
next();
});
}, () => {
console.log(data);
});
// 第一次执行2个,成功就依次往下排...所有都完成直接返回结果
asyncPool可以限制并发的数量
使用JS实现并发请求接口的解决方案
- 要点:tasks是一个数组,每一项就是一个异步请求「基于Promise管理」
- 思路:根据并发数量创建对应工作区,依次将每一个任务放在工作区执行,每个工作区也基于Promise来管理
function createRequest(tasks, pool) {
pool = pool || 5;
let results = [],
together = new Array(pool).fill(null),
index = 0;
together = together.map(() => {
return new Promise((resolve, reject) => {
const run = function run() {
if (index >= tasks.length) {
resolve();
return;
};
let old_index = index,
task = tasks[index++];
task().then(result => {
results[old_index] = result;
run();
}).catch(reason => {
reject(reason);
});
};
run();
});
});
return Promise.all(together).then(() => results);
}
createRequestAll(tasks, 2).then(res => {
// 都成功,整体结果才成功,按顺序存储结果
console.log('成功', res)
}).catch(err => {
// 只要有失败,则整体失败
console.log('失败', err)
})
这样就实现了,多个任务并发请求时的限制