同步和异步的理念,一直都知道,但是却不知道他们的来龙去脉是什么,找了一篇不错的文章,来学习总结下一下,今天就来看看吧。
1 、单线程
- 单线程的概念
- 大家熟悉的Java,就是一门多线程语言,后端常常利用Java的多线程处理各种各样的事,比如文件的上传下载等。
- 而JavaScript是否也可以支持多线程呢?
- 答案是否定的,javascript是一门单线程语言,因此,他在同一时间只能做一件事。
- 单线程意味着,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个;比如说下面这段代码:
// 同步代码 funnction fun1(){ console.log(1) } funnction fun2(){ console.log(2) } fun1() fun2() //输出 1 2- 很容易看出,输出会一次输出1、2,因为代码是从上到下执行,执行完fun1(),才继续执行fun2();
- 但是如果fun1()中的代码执行的是读取文件或者ajax操作,文件的读取和数据的获取,都需要一定时间,难道我们需要完全等到fun1()执行完才能继续执行fun2()么?
- 为了解决这个问题,后面才会有同步和异步的概念。
1.1 、JavaScript为什么是单线程?
- JavaScript的单线程,与它的用途有很大的关系。
- 因为
JavaScript的作为浏览器的脚本语言,主要用来实现与用户的交互,利用JavaScript,我们可以实现对DOM的各种各样的操作; - 如果JavaScript是多线程的话,一个线程在一个DOM节点中增加内容,另一个线程要删除这个DOM节点,n那么这个DOM节点是要增加还是删除呢?这会带来很复杂的同步问题,所以js是单线程的。
2、同步任务和异步任务
- (1)为什么会有同步和异步?
- 因为Js的单线程,因此同个时间只能处理一件事,所有的任务都需要排队,前一个任务执行完,才能继续执行下一个任务;
- 但是如果前一个任务执行的时间很长,比如文件的读取或ajax操作,后一个任务就不得不等着,拿ajax来说,当用户向后台获取大量的数据时,不得不等到所有的数据都获取完毕才能进行下一步操作,用户只能在那里干等着,严重影响用户体验。
- 因此,Js在设计的时候,就已经考虑到这个问题,主线程可以完全不用等待文件的读取完毕或ajax的加载成功,可以先挂起处于等待中的任务,先运行排在后面的任务,等到文件的读取或ajax有了结果后,再回过头执行挂起的任务,因此,任务就可以分为同步任务和异步任务。
- (2)同步任务 同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站的渲染过程,比如元素的渲染,其实就是一个同步任务。 -(3)异步任务 异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务执行了,该任务才会进入主线程。
function fun1(){
console.log(1)
}
function fun2(){
console.log(2)
}
function fun3(){
console.log(3)
}
fun1();
setTimeout(function(){
fun2();
},0);
fun3();
//输出
1
3
2
有了异步,就算fun2()里面是文件的读取或ajax这种耗时的任务,也不怕fun3()要等到fun2()执行完才能执行;
?????我的疑问
- 现在我知道什么是异步了,但是异步是自动识别的吗,是Js自己有这个机制可以自己判断执行的吗;
promise的简介
- promise是异步编程的解决方案,比起传统的解决方案:回电函数和事件,更合理更强大;
- 所谓promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作的结果)。
- 从语法上说,promise是一个对象,从他可以获取异步操作的消息;
- 有了promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数;
函数的写法
- promise对象是一个构造函数,用来生成promise实例;
- 下面创造了一个promise实例;
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
- promise构造函数,接受一个函数作为参数,该函数的两个参数,分别是
resolve和reject; - 这个
resolve和reject,它们是两个函数,由Js引擎提供,不用自己部署; resolve函数的作用,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
promise实例生成后用then方法
- then方法,分别指定resolved和rejected状态的回调;