文章目录
一、异步
1. 什么是异步
- 异步(Asynchronous, async)是与同步(Synchronous, sync)相对的概念。
- 在我们学习的传统单线程编程中,程序的运行是同步的(同步不意味着所有步骤同时运行,而是指步骤在一个控制流序列中按顺序执行)。
- 而异步的概念则是不保证同步的概念,也就是说,一个异步过程的执行将不再与原有的序列有顺序关系。
- 简单来理解就是:同步按你的代码顺序执行,异步不按照代码顺序执行,异步的执行效率更高。
2. js中有哪些异步程序
- 客户端
- 计时器
- ajax
- 服务端(Node.js)
- fs文件操作
- 数据库操作
setTimeout(function(){
console.log("异步程序1");
}, Math.round(Math.random()*1000));
setTimeout(function(){
console.log("异步程序2");
}, Math.round(Math.random()*1000));
setTimeout(function(){
console.log("异步程序3");
}, Math.round(Math.random()*1000));
3. 异步程序带来的问题
- 异步程序虽然可以极大的提升程序的执行效率,但也带来了一些不可避免的问题。最常见的就是无法保证程序的执行顺序,导致无法在同步状态下获取异步程序数据等
二、Promise用来解决什么问题
1. 什么是回调地狱
- 回调函数嵌套调用,根据外层异步程序执行结果,调用内层异步程序
setTimeout(function(){
console.log("异步程序1");
setTimeout(function(){
console.log("异步请求2");
setTimeout(function(){
console.log("异步请求3");
}, Math.round(Math.random()*1000));
}, Math.round(Math.random()*1000));
}, Math.round(Math.random()*1000));
- 回调地狱的缺点:代码可读性低,不利于查错,异常处理机制较差,浪费性能
2. 使用Promise优化回调地狱
- Promise的简单说明
- 使用Promise优化回调地狱
- Promise的链式调用可以很好的解决回调地狱问题
asyncFunc1().then(response => {
return asyncFunc2();
}).then(response => {
return asyncFunc3();
}).then(response => {
// 所有异步完成后的其他操作
})
- 使用Promise之后的优势
- 方便阅读
- 查错方便
- 状态管理
- …
三、Promise的使用
1. Promise的基本状态
- 三种状态的含义和特点
- pending:正在进行时…
- fulfilled:完成
- rejected:失败
2. Promise的基本语法
创建Promise实例,立即传入回调函数
new Promise((resolve, reject)=>{
console.log("正在进行时");
resolve("已完成")
reject("已失败")
})
3. Promise实例的方法
promise.then()
- promise实例状态为成功时执行
- 参数:回调函数;回调1用来处理成功状态,回调2用来处理失败状态,回调2可选
- 返回值:当前promise实例状态对应的回调函数的返回值,这个返回值必然是一个新的Promise实例,哪怕主动返回的不是Promise实例,也会被处理成Promise实例
promise.catch()
- promise实例状态为失败时执行
- 参数:回调函数,用来处理失败状态
- 返回值:回调函数的返回值
promise.finally()
- promise实例状态为成功或失败时都会执行,表示当前promise结束了
- 参数:回调函数,用来处理结束后的状态
- 返回值:回调函数的返回值
4. 使用Promise实例的方法优化回调地狱问题
- 场景描述
- 解决方式:链式回调
- 总结
5. Promise类的方法
Promise.resolve()
- 返回一个成功状态的Promise实例
- 参数:成功状态下的数据
Promise.reject()
- 返回一个失败状态的Promise实例
- 参数:失败状态下的数据
Promise.all()
- 用于将多个 Promise 实例,包装成一个新的 Promise 实例。
- Promise.all()全部子实例都成功才算成功,只要有一个子实例失败就算失败。
- 参数:多个Promise实例的数组
Promise.any()
- 用于将多个 Promise 实例,包装成一个新的 Promise 实例。
- Promise.any()只要有一个子实例成功就算成功,所有子实例失败才算失败。
- 参数:多个Promise实例的数组
Promise.race()
- 用于将多个 Promise 实例,包装成一个新的 Promise 实例。
- Promise.race()赛跑机制,取决于最先执行结束的子实例的状态
- 参数:多个Promise实例的数组
Promise.allSettled()
- 用于将多个 Promise 实例,包装成一个新的 Promise 实例。
- Promise.allSettled()所有子实例结束,新实例才会完成,包含所有子实例的状态
- 参数:多个Promise实例的数组
四、异步的终极解决方案:Async / Await
async
关键字,在函数的function
关键字之前使用,用于表示当前函数是一个异步函数,且函数执行结果自动返回一个成功状态的Promise
实例,这个异步函数内的return
关键字用于给这个成功状态的Promise
实例返回成功时的数据。
async function fn1(){}
console.log(fn1()); // Promise {<fulfilled>: undefined}
async function fn2(){
return "hello";
}
console.log(fn2()); // Promise {<fulfilled>: 'hello'}
fn2().then(res=>{
console.log(res); // hello
})
await
关键字只能在async
声明的异步函数中使用,表示等待。等待一个异步执行结束并返回成功状态时的数据。await
可以将异步的函数同步执行,await
一般用于等待Promise
的状态
async function fn(){
const res = await test();
console.log(res); // success
}
function test(){
return new Promise((resolve, reject)=>{
setTimeout(function(){
resolve("success");
},Math.random()*1000)
setTimeout(function(){
reject("error");
},Math.random()*2000)
})
}