异步编程
什么是同步编程和异步编程
同步变成就是将代码一步一步往下执行
异步编程就是执行一段代码A,我不等待他出结果,我会为他设置一个处理代码,当A出结果时,直接去调用那个处理代码去处理他,而我本身就不会再去管代码A了,代码会继续往下执行,等到A出结果了,直接让他执行之前设置好的处理代码就行了
为什么需要异步编程
JavaScript的执行环境是单线程的,客户端浏览器的UI渲染和js执行是共享一个线程的,如果js代码运行很长,那么UI就会假死,页面就会没有反应出现类似卡死的情况,为了解决这种情况,就需要用到异步编程
Promise
什么是 Promise
Promise 是异步编程的一种解决方案,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
Promise 的特点
- Promise 对象状态不受外界影响,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
- Promise 的状态一旦改变,就不会再改变 resolved ( 已定型 )
- Promise 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
- Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise 的缺点
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消
- 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
- 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
Promise 的基本用法
let a = 10;
let promise = new Promise(function(resolve, reject) {
if (a == 10){
resolve('成功');
}else{
reject('失败');
}
});
promise 对象通过new操作符创建,里面的function为回调函数,该回调函数接收两个参数(resolve,reject),成功调用和失败调用
Promise 方法
promise.then
包含两个参数(res,err)
promise.then(res => {
console.log(res);
},err =>{
console.log(err);
})
若是res,控制台显示'成功'
若是err,控制台显示'失败'
promise.catch
专门用来捕获错误,相当于上面的promise.then 的err
promise.catch(err => {
console.log(err);
})
控制台显示'失败'
promise.reslove
把promise.resolve( )括号里面的东西变成 promise 对象,且为 reslove 状态,用于转对象
let p1 = promise.resolve('aaa');
p1.then(res => {
console.log(res);
});
等价于
let p1 = new promise(resolve => {
resolve('aaa')
});
p1.then(res => {
console.log(res);
});
promise.reject
类似上面的 promise.reslove 将括号内的东西变成 promise 对象,且为 reject 状态
代码可比较上面的promise.reslove
promise.all
用来批量处理 promise 对象
promise.all([p1,p2,p3]) 把promise打包,放在一个数组里面,打包完以后还是一个promise对象,但是要确保所有打包的promise对象都是resolve状态
let p1 = promise.reslove('aaaa');
let p2 = promise.reslove('bbbb');
let p3 = promise.reslove('cccc');
promise.all([p1,p2,p3]).then(res =>{
console.log(res);
})
promise.race
数组中只要有成功(resolve)就返回,失败(reject)之后后面全部不显示
let p1 = promise.reslove('aaaa');
let p2 = promise.reject('bbbb');
let p3 = promise.reslove('cccc');
promise.race([p1,p2,p3]).then(res =>{
console.log(res);
})
async
什么是 async
async用于异步操作,大大简化了异步操作的步骤
async 的基本用法
async function fn(){ //表示fn函数变为异步函数
let result = await xxx //表示后面的结果需要等待
}
async 的特点
- await 只能放在async函数中
- await后面可以是一个 promise 对象 ,也可以是数字、字符串、布尔值
- 整个async函数 返回的也是promise 对象
- 只要await语句后面promise状态变成reject,那么整个async函数就会中断执行
async 实例
以文件读取为例的代码
假设文件a.txt内容为aaa,b.txt内容为bbb,c.txt内容为ccc
const fs = require('fs');
//简单封装
const readfile = function(filename){
return new promise((resolve,reject) => {
fs.readfile(filename,(err,data) => {
if(err) reject(err);
resolve(data);
})
});
}
//读取文件
async function fn(){
let f1 = await readfile(a.txt);
console.log(f1.toString());
let f2 = await readfile(a.txt);
console.log(f2.toString());
let f3 = await readfile(a.txt);
console.log(f3.toString());
}
fn();
显示aaa,bbb,ccc
特点4代码
async function fn(){
await promise.reject('出现问题');
await promise.resolve('没毛病');
}
fn().then(res =>{
console.log(res);
}).catch(err =>{
console.log(err);
})
控制台只显示'出现问题',没显示'没毛病'
避免特点4的代码
使用try{}catch
async function fn(){
try{
await promise.reject('出现问题');
await promise.resolve('没毛病');
}catch(e){}
}
fn().then(res =>{
console.log(res);
}).catch(err =>{
console.log(err);
})