今天在知乎看到一篇文章https://zhuanlan.zhihu.com/p/...,讲的是宏任务与微任务
我以为我明白了
IO、settimeout都属于宏任务,事件循环的执行过程为script宏任务-》同步代码-》微任务-》渲染-》宏任务
直到我启node服务,输入了以下代码,才发现并没有理解
按照之前的理解,settimeout的time设置为0,那么它应该在任务队列的第一位。在清空执行栈中的同步代码后,应该先执行settimeout的function,再执行执行网络请求
可node服务接收到了网络请求,settimeout中的alert并没有阻止网络请求,为什么?网络请求不是IO吗?不是宏任务吗?难道网络请求比setTimeout(()=>{},0)更快进入任务队列?
setTimeout(() => {
console.log('宏任务执行1');
alert('暂停');
}, 0)
//自己封装的axios请求方法
App._post_form('adminUser/login', {}, (res) => {
}, (res) => {
console.log('IO结束then微任务执行2');
})
//alert('暂停');
有朋友回答是因为网络请求发起是同步的,或者网络请求已经在其它线程发起,那么为什么主线程中的alert却可以阻塞网络请求呢?
可以看到此时并没有发起网络请求
封装的方法,较长
/**
* post提交
*/
_post_form(url, data, success, fail, complete) {
let _this = this;
data.token = _this.getCookie('token');
data.time = new Date().getTime();
console.log('准备_post_form请求:' + url)
/*因为 axios 发送数据时不是以 formData 的形式发送的,而 大多数后端 接收的是以 formData 形式的数据。所以只好把数据在请求之前转换一下。*/
var params = new URLSearchParams();
Object.keys(data).forEach((key) => {
params.append(key, data[key]);
});
axios({
method: 'post',
url: _this.api_root + url,
data: params,
}).then(function (res) {
console.log('_post_form--success(res)', res);
//状态码不对
if (res.status !== 200 || typeof res.data !== 'object') {
layer.msg('网络请求出错');
return false;
}
//登录态失效, 重新登录
if (res.data.code === -1) {
layer.alert(res.data.msg, function (index) {
layer.close(index);
window.location.href = "/login";
});
return false;
//服务器返回错误
} else if (res.data.code === 0) {
// layer.alert(res.data.msg, function (index) {
// layer.close(index);
fail && fail(res);
// });
return false;
}
//正常返回
success && success(res.data);
//通用方法
complete && complete(res);
}).catch(function (err) {
console.log('_post_form--err(res)', err);
//通用方法
complete && complete(res);
});
},
发起网络请求的代码是同步的,返回结果的过程是异步的。
当前端发起fetch请求时,setTimeout还等在这个同步代码执行。当请求发起后,这个网络传输过程就已经不归前端管了,也就是已经处于pending状态。这个过程中即使alert阻断了js代码执行,数据已经在网络传输中了,也会正常返回服务端的结果。之所以F12还是显示pending状态,是因为alert阻断了返回结果的后续代码,并且F12没有及时更新。如果你在F12的NetWork里点击一下这个请求,更新一下它的页面状态,它的状态码已经变为200,说明这个请求已经成功完成与后端的交互。但是由于alert阻断,后续的代码无法执行而已。
目前测试出来两个结果:都是同步的情况下,axios会被后续的alert阻断,fetch和直接原生写 xhr 4个步骤都不会被阻断。那么可以推测一原因是axios封装的原因导致的,楼主研究下源码吧.
大致看了下axios的源码,之所以axios会被阻断,是因为调用axios后,返回的是一个promise.then,也就是说axios本身就已经变成异步的了,并且它是在then方法里发起的请求...