Promise
同步和异步:
同步:一件事做完了才到另一件事(与现实中的同步相反)
异步:在做一件事请,这件事还没做完就开始做另一件事(有一段时间同时做两件事)
异步是非阻塞的,异步逻辑与主逻辑相互独立,主逻辑不需要等待异步逻辑完成,而是可以立即继续下去。怎么理解呢?就是可能有一件事卡住了做不了,但是不影响其他事情继续下去。
所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
new Promise((resolve,reject) => {
setTimeout(()=>{
resolve("异步请求成功的数据"); //如果请求成功则把参数传递给then
reject("异步请求失败了"); //如果请求失败则把参数传递给catch
},1000)})
.then((data) => { //接收传输的数据
console.log(data); //处理数据
})
.catch((err) => { //接收请求失败的数据
console.log(err); //处理
})
.finally((all) => {
console.log(all);
})
.then返回的是一个promise实例,所以可以进行链式调用。
Promise.all
可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败返回值是不同的,全部成功时返回的是结果数组,有一个失败则返回最先失败的的promise结果。
Promise.all([p1,p2,p3...]).then(...)
Promise.all([
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("第一个请求");
},1000)
}),
new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("第二个请求");
},2000)
})
]).then((result)=>{
console.log(result[0]);
console.log(result[1]);
})
Promise.race
顾名思义race就是赛跑的意思,跟Promise.all差不多,只不过是就返回那个最先完成的结果,不管那个结果是成功还是失败。
Async / await
也是用来处理异步,其实是Generator函数的改进,背后原理就是Promise
async
async function f1(){
return "abc"
}
/*
async 自动包装成Promise对象,等价于
function f1(){
return new Promise((resolve) => {resolve("abc")})
}
*/
await
await只能放在async函数里面
async function f1(){
return new Promise((resolve,reject) => {resolve("f1")})
}
async function f3(){
try {
var c = await f1();//下面的代码阻塞,只有await完了才能继续执行
console.log(c);
} catch (error) {
console.log("error");//如果f1是reject,必须使用trycatch才能继续执行下面的代码哦。
}finally{
}
console.log("执行完了");
}
宏任务和微任务
宏任务:script的整体代码,setTimeout,setInterval,setImmediate
微任务:promise.then,process.nextTick
js 是单线程执行的,js中的任务按顺序一个一个的执行,但是一个任务耗时太长;
那么后面的任务就需要等待,为了解决这种情况,将任务分为了同步任务和异步任务;
而异步任务又可以分为微任务和宏任务。
script代码块就是一个宏任务,执行一个宏任务,先执行同步代码,遇到异步代码(promise,setTimeout等)会让他们进行排队,分别排两条队。一条是宏任务S,一条是微任务P。执行完同步任务后执行微任务,同样同步任务立即执行,遇到异步任务进行排队。把全部微任务执行完就执行宏任务,宏任务执行完一个就会去清理微任务队列,所以在宏任务里面的微任务会比外面的宏任务先执行。
图解:
举个栗子: