客套话
文章涉及的内容可能不全面,但量很多,需要慢慢看。我花了很长的时间整理,用心分享心得,希望对大家有所帮助。但是难免会有打字的错误或理解的错误点,希望发现的可以邮箱告诉我ghui_master@163.com,我会及时的进行修改,只希望对你有所帮助,谢谢。
重要性
接下来呢,我们把原生js里有一个非常重要的点 JS同步异步编程 来详细的看一下 , JS同步异步编程 不仅在面试中经常被问到,而且也是我们在真实的项目开发中,我们能不能有效的管控我们的数据请求,管控我们的异步操作,以及在项目当中我们很多的业务逻辑中,我们都得大量的应用同步异步编程的处理,那么此时需要我们把同步异步编程能够精准的,进准到骨子里的去掌握下来
JS 中的同步和异步编程
JS运行在浏览器中(浏览器只分配一个线程来运行JS =>JS是单线程的)
JS单线程导致大部分任务都是同步任务,只有及个别的事情属于异步的,如下:
- 事件绑定
- 定时器
- AJAX(AXIOS) / FETCH(天生就是异步的)
- Promise中的同步异步
Promise中的同步异步
- new Promise的时候,传递的exector函数一定是立即执行的,它属于同步的
- 基于then 或者 catch 存放的方法执行是异步的
new Promise((resolve, reject) => {
console.1og(1);
resolve(); //=> resolve()执行才会进入.then
}). then(() => {
console .1og(2);
});
console.1og(3);
<!--输出
1
3
2
分析:
当new Promise的时候 (resolve, reject) => {
console.1og(1);
resolve(); //=> resolve()执行才会进入.then
}
1.exector函数是立即执行的
2.当执行完exector后,虽然是执行了resolve(); 但是不会立马把.then 中的方法立即执行,而是new Promise的 exector执行完之后,先执行then,通过 then 把 它里面写的这个方法函数 () => {
console .1og(2);
} 存起来 ,什么时候这些函数该执行呢
3.等到主线程的 console.1og(3); 执行完以后,主线程的任务都结束了,才会去把 resolve();这个执行控制 () => {
console .1og(2);
} 它执行;
-->
- async / await 也是异步的,尤其是await
await 是同步还是异步?
异步,虽然把它理解为等待同步状态,但他一定是异步的
async function fn( ) {
await 10;
console.1og(1);
}
fn();
console.1og(2);
<!--输出
2
1
分析:
如果是同步的,我们先执行的fn();
然后进入先等 await 10; 他没有出来之前,后面的不会执行,
如果是同步的 包括 console.1og(2); 也不会执行 ,
但是进入fu 后它里面的没有执行就执行 console.1og(2);先输出了
说明 await一定是异步的
-->
- generator 函数
<!--
在 generator 中执行一个方法,它面的代码不会执行,
当我们只有通过 gt.next();后,代码才会一步一步执行,也可以理解为异步,
async 和 await 就是基于generator构建出来的
----------------------------------------------------
创建一个generator函数 名字用*标识的名字,
都属于generator生成器函数
-->
function* fn() {
yield 10;
console.1og(1);
yield 20;
console.1og(2);
}
let gt = fn(); // 在 generator 中,执行fn方法,返回一个对象,它里面的代码不会执行
console.log(gt);
gt.next(); // 只有通过next才能控制代码一点一点的往下走
gt.next();
gt.next();
console.1og(3);
<!--输出
object [Generator] {}
1
2
3
当只有一个 gt.next();时 只会输出 一个 3
-->
JS谁如何构建出异步编程的效果?
- Event Loop 基于 "事件循环机制" (Event Queue 事件队列)
setTimeout(() => {
console .1og(1);
},50);
setTimeout(() => {
console.1og(2);
}, 0); //=>不是立即执行,有一个最小的反映时间
console. time('FOR');I
for(leti=0;i<100000;i++){}
console. timeEnd('FOR'); //=> 循环时间<=10MS
setTimeout(() => {
console.1og(3);
}, 20);
console.1og(4);
<!--输出
FOR:3.5ms
4
2
3
1
-->
-
Event Queue 事件队列中存在两个任务队列:
-
macro task queue 宏任务队列 (定时器、事件绑定、AJAX ... )
-
micro task queue 微任务队列 (Promise、async/await ...)
-
-
只要主栈执行完,到Event Queue中去找要执行的任务
- 执行顺序永远都是先找微任务,微任务没有了 ,再找宏任务
- sync同步 -> micro微任务 -> macro宏任务
讲了这么多,检测一下吧
这是一个最具经典的面试题 字节跳动 今日头条
是不是题都没看明白 哈哈哈
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console. log( 'async2');
}
console.log('script start');
setTimeout(function (){
console.log('setTimeout');
}, 0);
async1();
new Promise(function (resolve) {
console.log('promise1');
resolve();
}).then(function () {
console.log('promise2');
});
console.log('script end');
<!--输出
给了答案也不知道是个啥鬼
控制台输出:
VM90:9 script start
VM90:2 async1 start
VM90:7 async2
VM90:15 promise1
VM90:20 script end
VM90:4 async1 end
VM90:18 promise2
VM90:11 setTimeout
node下运行
script start
async1 start
async2
promise1
script end
promise2
async1 end
setTimeout
-->