Promise
- 是ES6引入的JS异步编程的解决方案
- promise是一个构造函数
- promise对象用来封装一个异步操作,并获取成功或失败的结果值
异步编程(默认使用回调函数)
回调地狱问题(代码不断缩进)【以fs文件操作为例】
const fs = require('fs')
fs.readFile('a.txt',(err,data1)=>{
if (err1) return "a.txt读取失败";
fs.readFile('b.txt',(err,data2)=>{
if (err2) return "b.txt读取失败";
fs.readFile('c.txt',(err,data3)=>{
if (err3) return "c.txt读取失败";
console.log(data1+data2+data3)
})
})
})
promise链式调用解决回调地狱问题【以fs文件操作为例】
const fs = require('fs')
const prm = new Promise((resolve,reject)=>{
fs.readFile('a.txt',(err,data)=>{
if(err) reject("a.txt读取失败")
resolve(data)
})
})
prm.then(function(value){
return new Promise((resolve,reject)=>{
fs.readFile('b.txt',(err,data)=>{
if(err) reject("b.txt读取失败")
resolve(data+value)
})
})
},function(reason){
return reason;
}).then(value=>{
fs.readFile('c.txt',(err,data)=>{
if(err) return "c.txt读取失败";
console.log(data+value)
})
},reason=>{
return reason;
})
async函数和await表达式解决地狱回调问题【以fs文件操作为例】
const fs= require('fs')
const util= require('util')
const min= util.promisify(fs.readFile)
async function fn(){
try{
let data1 = min(a.txt)
let data2 = min(b.txt)
let data3 = min(c.txt)
console.log(data1+data2+data3)
}catch(e){
console.log(e)
}
}
Promise语法
promise对象的属性
属性名 | 含义 |
---|
PromiseState | 表示promise对象的状态 |
PromiseResult | 表示promise对象的值 |
promise对象的状态『PromiseState』
- 状态改变:pending–> resolved 调用resolve()
- 状态改变:pending --> rejected 调用reject() 或 throw ‘111’
- 一个promise对象状态只能改变一次
new Promise((resolve,reject)=>{
resolve('222')
reject('111')
})
- 成功的数据称为value,失败的数据称为reason
PromiseState属性的值 | 含义 |
---|
pending | 未决定的 |
resolved/fulfilled | 成功 |
rejected | 失败 |
promise对象的值『PromiseResult』
- 存储的是异步任务成功或失败的结果
- resovle()和reject()函数可以修改这个值
promise工作流程
promise函数
- Promise()构造函数
- resolve()函数,在构造函数内部,表示执行成功
- reject()函数,在构造函数内部,执行失败
new Promise((resolve,reject)=>{
if (err)reject()
resolve()
})
- Promise.prototype.then()方法:then方法返回的也是一个promise对象,所以可以链式调用
- onResolved函数:成功时调用value=>{}
- onRejected函数:失败时调用reason=>{}
p.then(value=>{},reason=>{})
- Promise.prototype.catch()方法
- onRejected函数:失败时调用reason=>{}
p.catch(reason=>{})
- Promise.resolve()方法:属于Promise对象,不属于实例对象
let pr = Promise.resolve(value=>{})
Promise.resolve("111")
let pr2 = Promise.resolve(new Promise(resolve,reject)=>{resolve("111")})
- Promise.reject()方法:属于Promise对象,不属于实例对象
let pr = Promise.reject(reason=>{})
Promise.reject("111")
let pr2 = Promise.reject(new Promise(resolve,reject)=>{resolve("111")})
- Promise.all()方法:属于Promise对象,不属于实例对象
let pr = Promise.all(promises=>{})
let pr1 =new Promise((resolve,reject)=>{resolve()})
let pr2 =new Promise((resolve,reject)=>{resolve()})
let pr3 =Promise.all([pr1,pr2])
- Promise.race()方法:属于Promise对象,不属于实例对象
let pr = Promise.race(promises=>{})
promise问题
- 构造函数改变promise状态
(1)构造函数里调用resolve() 状态是:pending–> resolved
(2)构造函数里调用reject() 或 throw ‘111’ 状态是:pending --> rejected - then函数里改变promise状态
(1)throw ‘111’ 状态是:pending --> rejected
(2)then函数里返回值是promise对象以外 状态是:pending–> resolved
(3)then函数里返回值是promise对象,由promise对象决定。成功就resolved,失败就rejected。
p.then(value=>{
throw '111'
return '111'
return new Promise((resolve,reject)=>{resolve())})
})
let pr1 =new Promise((resolve,reject)=>{
})
pr1.then(value=>{console.log('111')})
pr1.then(value=>{console.log('222')})
- 异常穿透:当then链式调用有多个时,不用在中间指定失败的回调,只要在最后指定失败的回调就可以了。
let pr1 =new Promise((resolve,reject)=>{
reject('aaa')
})
pr1.then(value=>{
console.log('111')
}).then(value=>{
console.log('222')
}).catch(reason =>{
console.log(reason)
})
let pr1 =new Promise((resolve,reject)=>{
reject('aaa')
})
pr1.then(value=>{
console.log('111')
return new Promise(()=>{})
}).then(value=>{
console.log('222')
})then(value=>{
console.log('333')
})
async 和await
- async函数和await表达式结合可以让异步代码像同步代码一样
async函数
- async函数返回结果是promise对象
- promise对象的结果由async函数执行的返回值决定
async function fn(){
return 'aaa'
throw new Error('aaa')
return new Promise((resolve,reject) => {resolve('成功')})
}
await表达式
- await必须写在async函数中
- await右边也可放一个表达式,一般为promise对象
- await返回的是promise成功的值
- 如果表达式是其他值,非promise对象,则直接将此作为await的返回值
- await的promise失败了,就会抛出异常,需要通过try catch捕获处理
const pm = new Promise((resolve,reject)=>{
})
async function fn(){
try{
let result = await pm;
console.log(result)
let result2 = await 20;
console.log(result2 )
}catch(e){
console.log(e)
}
}