js单线程及异步笔记
- js运行时默认是单线程的,除非显式的使用或创建了其他线程
- 浏览器Web Workers
- nodejs通过node:worker_threads
- js里没有c或java中的互斥锁等同步对象(单线程不需要)
- js单线程(主线程)里有任务队列和微任务队列
- 所以一般通常回调也是在主线程中执行的
- 关于微任务 mdn
同步与异步
同步是阻塞的,上一行执行完才能执行下一行,从上到下一行一行执行的
//示意同步代码,这个是最普通、最常见的场景(普通的脚本文件中最多)
function sleepS(second){
console.log(`start time point:${new Date().toLocaleTimeString()}`);
let start = new Date();
let startMs = start.getTime();
let reachTime = false;
do {
let cur = new Date();
let curMs = cur.getTime();
if((curMs - startMs) > 1000*second)
{
reachTime = true;
}
}while(!reachTime);
console.log(`end time point:${new Date().toLocaleTimeString()}`);
}
console.log('this is first line!');
sleepS(2);
sleepS(3);
console.log('this is last line!');
异步是调用后,调用方不用等待结果,可以继续执行其他代码;异步结果会通过回调方式通知的
function asyncCode(){
console.log(`this is first line!`);
setTimeout(()=>{console.log(`this 3, is called,by task queue!`);},1);
console.log(`this 2!`);
}
asyncCode();
该函数输出如下:
this is first line!
this 2!
this 3, is called,by task queue!
该示例说明:
- setTimeout是异步执行的
- 主线程存在任务队列
异步函数的来源
- 运行时提供
- 浏览器环境,比如setTimout 、setInterval 、XMLHttpRequest等
- node环境,几乎所有api都是异步的
- 自己封装的函数(也是异步的,不阻塞、结果通过回调等方式通知)
- 不基于运行时提供的能力,纯粹的js是没法写出原生的异步的函数的
- 其实c++也是;语言本身并不提供异步的实现;只是借助操作系统的线程,提供了一些实现异步的方法;
- 语言本身提供了一些标准库,对操作系统 的线程进行了封装,只是更方便使用、可移植(std::thread、std::async)
- c++语言的std::function也只是对函数指针的一种升级
Promise
const bar = () => console.log('bar')
const baz = () => console.log('baz')
const foo = () => {
console.log('foo')
setTimeout(bar, 0) //宏任务再下一次队列开始时执行
new Promise((resolve, reject) =>{
//promise中的代码是主线程中同步执行的,一般是负责触发调用异步的函数,很快完成,不会阻塞
console.log("after foo,befor baz");
resolve('应该在 baz 之后、bar 之前')}
).then(resolve => console.log(resolve))
baz()
}
foo()
async和await
- 是对promise的优化
- async修饰函数是标注该函数是异步的,或者不会阻塞的
- 后续继续补充
https://developer.mozilla.org/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide
1
2