众所周知,JS 是一门单线程语言,可是浏览器又能很好的处理异步请求,那么到底是为什么呢?
JS 的执行环境一般是浏览器和 Node.js,两者稍有不同,这里只讨论浏览器环境下的情况。
JS 执行过程中会产生两种任务,分别是:同步任务和异步任务。
console.log("script start");
setTimeout(function () {
console.log("setTimeout");
}, 0);
Promise.resolve()
.then(function () {
console.log("promise1");
})
.then(function () {
console.log("promise2");
});
console.log("script end");
<script>
中的代码):script start
script end
promise1
,then 之后产生一个微任务,加入微任务队列,当前微任务队列(promise2)promise2
setTimeout
new Promise(..)
中的代码,也是同步代码,会立即执行。只有then
之后的代码,才是异步执行的代码,是一个微任务。console.log("script start");
setTimeout(function () {
console.log("timeout1");
}, 10);
new Promise((resolve) => {
console.log("promise1");
resolve();
setTimeout(() => console.log("timeout2"), 10);
}).then(function () {
console.log("then1");
});
console.log("script end");
<script>
]script start
promise1
,直接 resolve,将 then 加入微任务,遇到 timeout2,加入宏任务。script end
then1
timeout1
timeout2
timeout2
// async/await 写法
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
// Promise 写法
async function async1() {
console.log("async1 start");
Promise.resolve(async2()).then(() => console.log("async1 end"));
}
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
async1();
setTimeout(() => {
console.log("timeout");
}, 0);
new Promise(function (resolve) {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
console.log("script end");
<script>
],微任务: []async1 start
async2
,并将 then(async1 end)加入微任务promise1
,直接 resolve,将 then(promise2)加入微任务script end
promise2
async1 end
timeout
const s = new Date().getSeconds();
console.log("script start");
new Promise((resolve) => {
console.log("promise");
resolve();
}).then(() => {
console.log("then1");
while (true) {
if (new Date().getSeconds() - s >= 4) {
console.log("while");
break;
}
}
});
setTimeout(() => {
console.log("timeout");
}, 2000);
console.log("script end");