异步专题
同步和异步是一种消息通知机制
同步:A调用B,B处理获得结果,才返回给A。A在这个过程中,一直等待B的处理结果,没有拿到结果之前,需要A(调用者)一直等待和确认调用结果是否返回,拿到结果,然后继续往下执行。
在 JS 中,正常的代码执行,全部走的都是同步模式,必须拿到一行的执行结果,再去走下一行
alert(1);
fn2();
function fn2(){
console.log(2); }
异步:A调用B,无需等待B的结果,B通过状态,通知等来通知A或回调函数来处理。
调用结果返回时, 会以消息或回调的方式通知调用者。
在 JS 中,定时器,动画帧 这些操作,都是异步操作,所以是在 回调函数中 处理执行后的内容
setTimeout(()=>{
console.log(1);
},100);
fn2();
function fn2(){
console.log(2); }
回调地狱
封装简易运动框架
最早我们处理异步消息通知,都是通过回调来处理的,但是回调多了,代码的结构就必然嵌套层级特别多,造成可读性和维护性的直线下降 - 这就是回调地狱
function BoxMove(){
move(box,"left",200,()=>{
// console.log("运动结束了");
move(box,"top",200,()=>{
move(box,"left",0,()=>{
move(box,"top",0);
});
});
});
}
Promise 对象
ES6的Promise对象是一个构造函数,用来生成Promise实例。
所谓Promise对象,就是代表了未来某个将要发生的事件(通常是一个异步操作)。
它的好处在于,有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
Promise 基本语法
new Promise(function(resolve,reject){
})
Promise 内部状态
- Pending 在等待(异步执行中)
- Fulfilled(标准)||Resolved 执行成功 - 调用resolve之后改变
- Rejected 执行失败 - 调用 reject 之后改变
then
promise.then(onFulfilled,onRejected)
参数:
onFulfilled
当Promise变成接受状态(fulfillment)时,该参数作为回调函数被调用(参考: Function)。该函数有一个参数,即接受的最终结果(the fulfillment value)。如果传入的 onFulfilled 参数类型不是函数,则会在内部被替换为(x) => x ,即原样返回 promise 最终结果的函数
onRejected
当Promise变成拒绝状态(rejection )时,该参数作为回调函数被调用(参考: Function)。该函数有一个参数,,即拒绝的原因(the rejection reason)。
promise的链式操作
let p1 = new Promise((resolve,reject)=>{
resolve(1);
}).then((data)=>{
console.log("resolve");
return {
a : 1
};
},(data)=>{
console.log("reject");
return {
b : 2
}
}).then((data)=>{
console.log("p2的resolve");
},(data)=>{
console.log("p2的reject");
});
Promise 的 then 方法,会给我们返回一个新的 Promise对象
新的 Promise 对象的执行状态:
1. 默认情况: 返回的是一个状态 为 resolve 的 Promise对象
2. 当then的回调函数返回的是一个 非Promis对象,
then返回的是一个状态为 resolve 的 Promise对象
Promise.reject
Promise.reject(reason) 返回一个状态为 Rejected 的 Promise 对象
参数:
reason 失败原因
Promise.resolve
Promise.resolve(value) 返回一个状态为 resolved 的 Promise 对象
参数:
value 将被Promise对象解析的参数
Promise.catch
捕获前一个promise抛出的错误
Promise.all
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例,当所有Promise都成功的时候,整个Promise.all才成功
Promise.race
与Promise.race方法类似将多个promise包装成一个新的promise实例
但是其中有一项的状态发生改变新的实例的状态就会随着改变
async函数
只要函数名之前加上async关键字,就表明该函数内部有异步操作。
该异步操作应该返回一个Promise对象,前面用await关键字注明。
当函数执行的时候,一旦遇到await就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句
async function fn(){
try{
let n1 = await new Promise((resolve)=>{
setTimeout(() => {
resolve();
console.log(1);
},1000);
});
let n2 = await new Promise((resolve)=>{
setTimeout(() => {
resolve();
console.log(2);
},1000);
});
let n3 = await new Promise((resolve)=>{
setTimeout(() => {
resolve();
console.log(3);
},1000);
});
}catch(err){
console.log(err);
}
}
fn();