前言
了解同步和异步
了解异步
1.宏任务与微任务
2.宏任务与微任务的执行顺序
了解Promise
1.Promise(承诺)
2.Prpmise的方法
了解async/await
1.async/await
试题
1.使用Promise与async/await分别输出1,2
2.再了解异步与同步的输出顺序
3.最后我们用setTimeout模拟异步操作,用Promise和Async/Await分别来实现下
总结
最近翻了许多资料去了解Promise,async/await。可以从一个出发点去理解,我们JavaScript是一门单线程语言(single thread,指一次只能完成一件任务,如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推),而异步在浏览器中大致分为(定时器模块、Ajax模块、DOM模块)
首先,什么是宏任务,微任务?
js 是一种单线程语言,简单的说就是:只有一条通道,那么在任务多的情况下,就会出现拥挤的情况,这种情况下就产生了 ‘多线程’ ,但是这种“多线程”是通过单线程模仿的,也就是假的。那么就产生了同步任务和异步任务。
异步任务分为宏任务,微任务。
宏任务 | 微任务 |
script |
Process.nextTick(node.js) |
setTimeout |
Promise |
setInterval |
MutationObserver |
setImmediate (浏览器暂时不支持,只有IE10支持) |
async/await |
I/O |
Object.observe |
UI Rendering |
|
requestAnimationFrame(存在争议) |
先执行同步再执行异步,异步遇到微任务,先执行微任务,执行完后如果没有微任务,就执行下一个宏任务,如果有微任务,就按顺序一个一个执行微任务
Promise,翻译过来是承诺,承诺它过一段时间会给你一个结果。从编程讲Promise 是异步编程的一种解决方案。下面是Promise在MDN的相关说明:
Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。
一个 Promise有以下几种状态:
这个承诺一旦从等待状态变成为其他状态就永远不能更改状态了,也就是说一旦状态变为 fulfilled/rejected 后,就不能再次改变。
Promise的方法有很多如resolve(),reject()then(),catch(),all(),race()等等,这里我就不细谈了
async/await
是一种建立在Promise之上的编写异步或非阻塞代码的新方法,被普遍认为是 JS异步操作的最终且最优雅的解决方案。相对于 Promise 和回调,它的可读性和简洁度都更高。毕竟一直then()也很烦。
async
是异步的意思,而 await
是 async wait
的简写,即异步等待。
所以从语义上就很好理解 async 用于声明一个 function 是异步的,而await 用于等待一个异步方法执行完成。
一个函数如果加上 async ,那么该函数就会返回一个 Promise
Promise用法
//使用Promise输出1,2
function foo(){
//利用Promise的resolve成功在调用then(resolve))返回的是成功的
Promise.resolve().then((resolve)=>{
console.log(1);
})
console.log(2);
}
foo()
//执行顺序为首先判断代码为同步还是异步
//判断Promise为异步,再判断为它为宏任务还是微任务,根据它是什么任务再放入它本身的队列当中
//首先执行同步代码,再进行异步代码
//结果为2,1
async/await再执行这段代码
async function foo(){
await Promise.resolve().then((resolve)=>{//await为步数,带有顺序,从上往下
console.log(1);
})
console.log(2);
}
foo()
//利用async/await调用函数
//输出的结果为1,2
//原因为async/await将异步转换成同步了
console.log('start');
Promise.resolve().then((resolve)=>{
console.log(1);
})
async function fn(){
console.log(2);
await console.log(3);
console.log(4);
}
fn()
setTimeout(()=>{
console.log("setTimeout1");
},0)
async function fn1(){
await new Promise(resolve=>{
setTimeout(()=>{
console.log('setTimeout2');
resolve()
},0)
})
}
fn1()
async function fn2(){
await Promise.resolve().then(resolve=>{
console.log(5);
})
}
fn2()
console.log('end');
结果为:
是不是与你的猜想不一样^v^
那我们来分析一下吧!
console.log('start'); //为同步
Promise.resolve().then((resolve)=>{//为异步 为微任务放入微任务队列
console.log(1);
})
async function fn(){//为同步
console.log(2);//为同步
await console.log(3);//为异步 并且为微任务下一个执行
console.log(4); //本来为同步,但是因为await,改变为微任务放入微任务队列
}
fn()
setTimeout(()=>{
console.log("setTimeout1"); //为异步 为宏任务放入队列
},0)
async function fn1(){//为同步
await new Promise(resolve=>{ //为同步
setTimeout(()=>{ //为异步 为宏任务放入队列
console.log('setTimeout2');
resolve()
},0)
})
}
fn1()
async function fn2(){
await Promise.resolve().then(resolve=>{//为异步 为微任务放入微任务队列
console.log(5);
})
}
fn2()
console.log('end');//为同步
//所以输出为 start,2,3,end
//1,4,5
//setTimeout1
//setTimeout2
现在是不是清晰了很多呢?
Promise
// 传入一个初始值
function sync(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 500), n)
// 定时器在n秒后触发
})
}
// 调用函数的也需要调用参数n
function fn1(n) {
console.log("start", n);
return sync(n)
}
function fn2(n) {
console.log("loading", n);
return sync(n)
}
function fn3(n) {
console.log("end", n);
return sync(n)
}
function fn(){
let num=0
fn1(num).then((num1)=>fn2(num1))
.then((num2)=>fn3(num2))
.then((res)=>{
console.log("result is",res);
})
}
fn()
async/await:
// 传入一个初始值
function sync(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 500), n)
// 定时器在n秒后触发
})
}
// 调用函数的也需要调用参数n
function fn1(n) {
console.log("start", n);
return sync(n)
}
function fn2(n) {
console.log("loading", n);
return sync(n)
}
function fn3(n) {
console.log("end", n);
return sync(n)
}
// 调用
async function init(){
let num=0;
let f1=await fn1(num)
let f2=await fn2(f1)
let result=await fn3(f2)
console.log("result",result);
}
init()
结果为:
其实Promise与async/await输出的结果是一样的,只是async/await会更好理解一些,所以我们认为async/await是Promise或者Generator的语法糖。更仔细的我也描述的不太好,大家可以参考文案:「硬核JS」深入了解异步解决方案 - 掘金 (juejin.cn)
哈哈哈,其实我没有总结
水平有限,欢迎指错
码字不易,大家有收获别忘了点个赞鼓励下