Open super-fool opened 3 years ago
exc
函数是一个同步函数,那么先执行,将该函数放入同步栈中,所以肯定先打印 1
,遇到了resolve,那么会将链式的第一个then
放入异步队列中,然后继续执行打印2
. 在打印2
后发现exc
函数内部的代码已全部执行完毕,然后推出同步栈,执行最外部的代码,打印4
. 执行完发现所有的同步代码都已经执行完毕,那么从异步队列中pop
异步代码进行执行。
所以最后的打印顺序为: 1, 2, 4, 3
接下来,我们改变一下:
function exec() {
new Promise((res) => {
console.log(1);
res();
console.log(2);
})
.then((res) => {
console.log(3);
})
.then((res) => {
console.log(5);
})
.catch((err) => {
console.log("err");
});
}
// exec();
await (exec());
console.log(4);
这样执行会是怎样的执行方式呢?
这里要注意:
await
只能在async函数中去调用才有效,如果不将exec()
用括号包裹着,便会报语法错误:SyntaxError: await is only valid in async function
现在随着现代前端代码逐渐迁移到了 ES Module(默认是严格模式),标准委员会也在计划扩大 await的使用场景,所以有了 !-top-level await 提案 。在这个提案里,只要是在 Module 环境下,我们是可以直接写 await的, 报错也做了相应的改变:Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
第一,我们在之前的代码中又添加了一个then
, 第二,我们将exec
函数用await进行执行。
那么我们首先要了解 await
,await
是一个generator().next()
, 或者说是一个Promise.resolve()
所以返回: 1, 2, 3, 4, 5
异步任务: 多个请求时同时请求的, 即并行的触发的. but! 每个请求的回调函数是注册到任务队列中的, 以FIFO的规则进行调用.
实现一个任务队列:
// 队列的方法有: enqueue, dequeue, front, isEmpty, size
let Queue = ~function() {
const items = new WeakMap();
class Queue {
constructor() {
items.set(this, []);
}
getQueue() {
return items.get(this);
}
enqueue(item) {
this.getQueue().push(item)
}
dequeue() {
this.getQueue().shift();
}
front() {
return this.getQueue()[0]
}
isEmpty() {
this.getQueue().length = 0;
}
return Queue;
}
}()
执行顺序?