JavaScript---异步函数async内部运行机制

前言

Async函数是ES7引入的用来操作异步的函数,在语法上,Async 函数与Generator 函数非常的类似,在对象性质上,Async 函数与Promise对象又是密不可分的。

一、JavaScript的运行机制

在我们探究Async函数内部运行机制执行,我们不得不来先说一说JavaScript这门语言的的运行机制。JavaScript的执行是单线程的,单线程的异步,其实只是按照某种规则以同步的方式分配利用CPU,而产生的异步效果。
在JavaScript内部,我们可以划分出来两种任务类型:

1.宏任务(macro-task)

类似:包括整体代码script,setTimeout,setInterval这样的语句都会开启一个宏任务,
当执行Script代码块时,则作为第一个宏任务启动。


每当启动一个宏任务,JavaScript都会将其置入一个称之为任务队列的任务池中,之后,一旦当前的宏任务结束时,线程将会在任务池中以任务置入的先后顺序来获取新的宏任务进入线程执行,周而复始,直至所有的宏任务结束。

需要注意的是:

如果当前的宏任务下有微任务,则执行完所有的微任务后才能空出线程,执行排在后面的宏任务

那么什么又是微任务呢?

2.微任务(micro-task)

类似: Promise 对象就是产生微任务的代表


每个微任务将会绑定到当前的宏任务下,微任务的置入以及取出机制与宏任务是一致的,但是,微任务在产生的同时还会绑定到当前运行的宏任务下面,也就是说,只有当前的微任务全部执行完毕,该宏任务才可能被执行结束。

每个微任务会被放入队列池(Event Queue),之后,线程若空出来则按放入的先后顺序执行

了解完JavaScript的运行机制,接下来就让我们来探究Async函数机制。


二、Async函数内部运行机制

理解下面代码运行:

function hh() {
	console.log("hhh");
	return "hhhhhhh";
}
async function kk() {
	console.log("kkk");
	return Promise.resolve("");
}
var qq = new Promise((resolve)=> { 
	console.log("qqq"); 
	resolve("qqqqqqqqqqqq");
});
qq.then((val)=> console.log(val));
async function test() {
	console.log("111111111111");
	const v1 = await hh();
	console.log('222222222222');
	const v2 = await kk();
	console.log('333333333333');
	console.log('444444444444');
}

test();
var pp = new Promise((resolve)=> { 
	console.log("ppp"); 
	resolve("pppppppppppp");
});
pp.then((val)=> console.log(val));
console.log("555555555555")

运行结果:

qqq
111111111111
hhh
ppp
555555555555
qqqqqqqqqqqq
222222222222
kkk
pppppppppppp
333333333333
444444444444

分析:

假设该语句在一个独立的Script块中。

语句开始,同时开启宏任务,由上而下顺序执行,

直到 new Promise 语句,此时输出console.log(“qqq”); 注意,此时创建了一个微任务,由Promise对象构造的新实例产生

接着运行到test();输出console.log(“111111111111”);

接着往下,遇到await语句,首先执行,输出:console.log(“hhh”); 之后立马返回一个Promise实例,然后跳出该函数,此时创建了一个微任务,由Promise对象构造的新实例产生,接着往下,

同样遇到Promise构造实例,输出console.log(“ppp”); 注意,此时创建了一个微任务,由Promise对象构造的新实例产生

接着往下,输出:console.log(“555555555555”),与此同时,该宏任务的基本语句执行完毕,开始执行微任务,该执行顺序是由置入微任务池的先后顺序先后调用执行
所以,输出:console.log(val),即"qqqqqqqqqqqq"

接着调用第二个微任务,即,Aysnc函数内部返回的那一个微任务,没有输出语句,接着往下执行,输出console.log(‘222222222222’);

然后再次遇到await语句,执行输出console.log(“kkk”);返回并创建一个微任务,即Promise实例,并跳出该函数,但发现没有语句可执行,于是空出线程取出微任务执行,此时轮到了第三个微任务,输出:console.log(val),即:“pppppppppppp”

之后,继续调用,即第二次Aysnc函数内部返回的微任务,该任务执行完毕,接着往下执行,输出:console.log(‘333333333333’);console.log(‘444444444444’);

博文不长,旨在精炼

AND

猜你喜欢

转载自blog.csdn.net/weixin_41087220/article/details/88935473