简单易懂的promise 与 async await 相关知识解析
什么是promise
为什么要有promise?其实promise的本质就是为了解决回调地狱的问题,例如
const fs = require('fs')
fs.readFile(filepath,(err,data)=>{
if(err){
return
}
fs.readFile(filepath,(err,data)=>{
//.....
fs.readFile(filepath,(err,data)=>{
//.....
fs.readFile(filepath,(err,data)=>{
//.....
})
})
})
})
禁止套娃! 其实就是为了解决因为不断调用回调函数导致的代码冗余不易读问题.
所以有了promise
那么promise又是怎么用的呢
promise的用法
promise是一个分支,当执行成功了,就会执行一个函数叫resolve,执行失败的时候,就会执行另外一个函数叫reject
new Promise((res,rej)=>{
//如果成功
res()
//如果失败
rej()
})
这是最简单的一种模型,但是如何理解 成功和失败呢?
我们拿fs.readFile方法来举例
我们都知道,当文件读取失败时就是失败,其他时候为成功,我们就可以写成:
new Promise((res,rej)=>{
fs.readFile(filepath,(err,data)=>{
if(err){
//失败时
rej(err)
return
}
//成功时
res(data)
})
})
到这一步,就创建好了一个简单的promise对象
是对象! 对象! 对象! 还要注意一点,promise中的内容会立即被执行
那下一步是,如何调用在对象中写好的res和rej方法呢?
promise提供了两个函数,一个是then,另外一个是catch,then会执行resolve的回调,catch会执行reject的回调
我们假设拿了一个变量readfile去接收promise
const readfile = new Promise()//....
readfile.then(data=>{
console.log(data.toString("utf8"))
}).catch(err=>{
console.error(err)
})
这样的话程序将会走一个分叉路口,当成功就会执行then中的回调函数,当失败就会执行catch中的回调函数,不会同时执行then和catch中的函数
注:一层回调写两个then时:
readfile('./a.js').then(data=>{
console.log(data)
}).catch(data=>{
console.log(data.toString())
}).then(data=>{
console.log(data)
})
这种写法第二个then会返回undefined,而不会再次打印data,因为第二个then是接收的是相当于回调地狱中第二层的回调函数了,如果要第二个then中还有值,需要我们在第一层回调中再次返回一个promise对象,传给下一个then来调用
async和await
async
如果要使用async,那么必须要放在方法中,因为async是用来修饰方法的关键词
await
await必须放在async修饰的函数中才能使用,用来修饰一个promise对象
当使用async方法并修饰了一个promise对象以后,就可以用try/catch来达到同样的效果
还是上面的例子,假设已经得到了一个readfile的promise对象
async function readFile(){
try{
const res = await readfile
console.info(res)
}catch(ex){
console.error(ex)
}
}
对比于
readfile('./a.js').then(data=>{
console.log(data)
}).catch(data=>{
console.log(data.toString())
}).then(data=>{
console.log(data)
})
而言,显得更加平面化
try中放的是成功(resolve)时的回调,catch中放到 是(reject)时的回调
const res = readfile 得到的res是成功时得到的数据而不是promise对象 因为用await进行了修饰
这样的代码更加易懂和简洁