首先我们要理解什么是同步和异步
同步:就是顺序执行的代码,调用这段代码我能直接获取到结果的就是同步
异步:就是稍后执行的代码,调用这段代码我可能没办法立即获取执行结果,需要通过别的操作才可以得到结果
但是JavaScript是以单线程的方式运行的,也就是同一时间只能进行一件事,试想一下,假如javascript是多线程的,如果线程1要删除一个DOM元素,节点2要让DOM元素运动起来并且显示,那么浏览器怎么知道你想要干什么,所以在诞生的时候选择了单线程
Runtime:

Javascript会将正在执行的任务放到栈(stack)中(特点:先进后出);(栈就是主线程)
Heap(堆)中保存着引用类型值,例如对象
Queue(队列) 任务队列由一系列待处理的任务组成,每个任务都有相对应的函数。当栈为空时则会从任务队列中取出一个任务处理。(特点:先进先出)
也就是说
在处理任务的时候,会先去处理主线程中的任务,然后等到主线程为空执行任务队列中的事件
那么说到这里必须说一说JS实现异步的一种机制:Event Loop (图片摘自阮一峰的Event Loop)

如果用户触发了一个事件,那么浏览器会将事件处理函数加入queue,当stack为空时,就去取出queue中的第一个任务
对于定时器,会在到达时间点时形成一个事件,定时器与其他事件不同的是靠事件循环不断检查系统时间来判断是否达到临界点来判断是否产生事件
来看几道小面试题
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(i);
},1000);
}我们同步创建了5个延时器,同步操作不会等待异步执行,所以在延时器循环已经执行完了,i的值是5,那么就会瞬间打印出5个5,这也就证明了异步的并发执行
setTimeout(function(){
console.log(1);
});
console.log(2);延时器即使设置时间为0 他也是异步操作,所以结果是先输出 2 后输出1 常见的异步代码:Ajax,时间,定时器,Promise
老一代的程序猿应该都经历过Callback Hell 可能因为要等待上一个异步操作返回数据,所以要一层回调套一层回调
所以ES6出现了Promise对象
new Promise((success,error)=>{
success(data); //成功回调
//error(data) //失败回调
}).then(callback);//.catch(callback)成功回调和失败回调只能执行一个 要么成功要么失败失败对应catch();
有了Promise对象 我们就可以使得异步操作同步执行了
function set(val,time){
return new Promise((success)=>{
setTimeout(()=>{
console.log(val)
success();
},1000*time);
})
}
var start=async function(){ //利用了es7的async function
await set("hello",3); //await 等待这个执行完再执行下一个操作
await set("world",1);
}
start();或者我们封装多个Promise
function deferOne(){
return new Promise((success)=>{
setTimeout(()=>{
console.log(1);
success()
},3000)
})
}
function deferTwo(){
return new Promise((success)=>{
setTimeout(()=>{
console.log(2);
success()
},1000)
})
}
new Promise((success)=>{
success();
}).then(deferOne).then(deferTwo);核心就是封装多个promise
本文探讨了JavaScript中的同步和异步概念。同步执行意味着代码按顺序执行,而异步执行允许在等待某些操作完成时继续进行其他任务。由于JavaScript的单线程特性,它依赖Event Loop来处理任务队列。文章还提到了异步实现,如定时器、Ajax、Promise,并讨论了如何使用Promise解决回调地狱问题。
746

被折叠的 条评论
为什么被折叠?



