JS的执行环境
JavaScript是单线程,类似于一条流水线生产,只能在生产完之后,再进行加工,而不能同时进行生产和加工。
单线程就意味着所有的任务都需要排队。只能在一个任务执行完成以后,再执行下一个任务,以此类推,如果期间有一个任务耗时时间比较长的话,就会阻塞后面的代码。
同步和异步的区别
- 同步 :执行完一个任务再执行下一个,如果当前执行的任务发生问题,下面的任务不再执行。
- 异步 :不管程序相应结果怎么样,都会执行所有代码 ,所以异步加载也叫非阻塞加载。
JS 是单线程的,但可以执行异步任务,这主要是因为 JS 中存在事件循环(Event Loop)和任务队列(Task Queue)。
js的执行过程
(1)所有同步任务都在主线程上执行,形成一个执行栈,主线程之外,还存在一个任务队列。
(2)先判断JS是同步还是异步,同步进入主线程,异步进入任务列队中等待。
(3)当执行栈中的所有同步任务执行完毕,任务列队就会通知主线程,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的(2)、(3)步。
js异步编程方法
回调函数
-
事例:有一个f1和f2函数依次等待执行,在同步的情况下f2函数在等待f1函数执行结果
-
异步方式解决
function f1(callback){
setTimeout(function () {
callback();
}, 1000);
}
f1(f2);
优点:容易理解,不容易造成阻塞
缺点:流程会有些混乱,且只能执行一个回调函数
事件监听
- 事例:按钮的点击事件触发时,触发sayHi函数
<input type="button" value="click" id="btn">
document.getElementById("btn").addEventListener("click",sayHi);
function sayHi(){
alert("hi");
}
优点:容易理解,可以绑定多个事件,有利于模块化。
缺点:必须以事件驱动
Promises对象
什么是Promise :用同步的方式写异步的代码,用来解决回调问题
-
Promise 的三种状态
01、pending : 等待中,或者进行中,表示还没有得到结果
02、resolved: 执行成功
03、rejected : 执行失败
new Promise(function(resolve, reject) {
if(执行成功) { resolve(data) };
if(执行失败) { reject(error) };
})
-
Promise对象有以下两个特点:
(1)对象的状态不受外界影响。 (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。
then()方法
Promise对象有一个then方法,then有两个参数,分别接收resolve和reject执行代码,then方法会返回一个Promise 对象,避免了回调地狱,因此形成了链式编程。
什么是回调地狱
- 金字塔形状和结尾的一大堆 }) ,代码看起来又长又乱且结构不清晰,可怕!
async1(function(){
async2(function(){
async3(function(
async4(funciton(){
async5(function()
...
});
});
));
});
});
- 用Promise.then()解决回调地狱
async1()
.then(function(){
//执行代码
}).then(function(){
//执行代码
}).then(function(){
//执行代码
})
....
- 补充:Promise对象还有一个catch方法,catch方法有一个参数接收reject执行代码。
P.then(null,fn(){}) 相当于 P.catch(fu(){})
Promise.all
var p = Promise.all([p1,p2,p3]);
-
用于将多个Promise实例,包装成一个新的Promise实例
-
当这个数组所有的Promise对象状态都变成resolved,才调用then方法
-
当p1, p2, p3其中之一状态变为rejected,p的状态也会变为rejected,并把第一个被rejected的promise的返回值,传给p的回调函数。