什么是promise
- 抽象表达
Promise是JS中进行异步编程的新的解决方案(Promise也支持回调),旧的方案是通过纯回调的方式 - 具体表达
从语法上:Promise是一个构造函数
从功能上:promise对象用来封装一个异步操作并可以获取其结果
promise对象状态改变
初始时是pending,表示未确定的状态,接下来可能有两种情况:
1、pending 变为 resolved
2、pending 变为 rejected
说明:只有这2种情况,不存在从resolved->pending或者rejected->pending的情况。并且一个promise对象只能改变一次
- 无论变为成功还是失败,都会有一个结果数据
- 成功的结果数据一般称为value,失败的结果数据一般称为reason
promise流程
Promise基本使用
<script>
//1、创建一个新的promise对象
const p = new Promise((resolve,reject) => { //reslove和reject是函数对象, (resolve,reject) => {} 叫执行器函数
//2、执行异步任务
setTimeout(() => {
const time = Date.now() //当前时间是偶数代表成功,否则代表失败
//3.1 如果成功,调用relosve(value)
if (time %2 == 0){
resolve('success data')
}else{
//3.2 如果失败,调用reject(reason)
reject('fail data')
}
},1000);
})
p.then( //指定成功的回调函数(即onResolved,表示当状态变为resolved时执行该回调函数)和失败的回调函数(onRejected,表示当状态变为rejected时执行该回调函数)
value => { //接收成功的value
console.log('成功的回调,数据是:',value)
},
reason => { //接收失败的reason
console.log('失败的回调,数据是:',reason)
}
)
</script>
执行器函数是同步回调还是异步回调?
根据之前的规则,加上console.log打印,看下输出:
<script>
//1、创建一个新的promise对象
const p = new Promise((resolve,reject) => { //reslove和reject是函数对象, (resolve,reject) => {} 叫执行器函数
console.log("执行 executor")
//2、执行异步任务
setTimeout(() => {
const time = Date.now() //当前时间是偶数代表成功,否则代表失败
//3.1 如果成功,调用relosve(value)
if (time %2 == 0){
resolve('success data')
}else{
//3.2 如果失败,调用reject(reason)
reject('fail data')
}
},1000);
console.log('executor 执行结束')
})
console.log('new Promise()之后')
p.then( //指定成功的回调函数(即onResolved,表示当状态变为resolved时执行该回调函数)和失败的回调函数(onRejected,表示当状态变为rejected时执行该回调函数)
value => { //接收成功的value
console.log('成功的回调,数据是:',value)
},
reason => { //接收失败的reason
console.log('失败的回调,数据是:',reason)
}
)
</script>
>>>执行 executor
>>>executor 执行结束
>>>new Promise()之后
>>>成功的回调,数据是: success data
执行器函数先输出,因此这里的执行器函数是同步回调。
执行器函数 打印执行 executor
->启动异步任务->new Promise()之后
,至此执行器函数结束,也就是new Promise()
函数结束并返回了promise对象。
总结:当得到promise对象时,异步任务已经启动了,正在执行,还没完成。所以返回promise对象是很迅速的,只要启动异步任务即可,不管它有没有完成。
Promise的作用
1、promise指定回调函数的方式更加灵活
- 纯回调方式
<script>
//成功的回调函数
function successCallback(result){
console.log("声音文件创建成功:"+result)
}
//失败的回调函数
function failureCallback(error){
console.log("声音文件创建失败:"+error)
}
//使用纯回调函数,在启动异步任务之前必须指定成功和失败回调函数
//createAudioFileAsync是一个耗时操作,第一个参数是创建音频文件的配置信息,successCallback是成功的回调函数,failureCallback是失败的回调喊
createAudioFileAsync(audioSettings,successCallback,failureCallback)
</script>
- 使用promise
<script>
function createAudioFileAsync(audioSettings){
const p = new Promise((resolve,reject) => { //执行器函数
//2、执行异步任务
startCreateAudioFile(audioSettings)
//返回promise对象
return p
}
//使用promise,createAudioFileAsync(audioSettings)返回promsie对象,异步任务在该promsie对象内部执行(即执行器中执行)
const promise = createAudioFileAsync(audioSettings);
//异步任务还在执行中,就指定回调函数
//promise.then(successCallback,failureCallback); #此时异步任务已经启动,还没有结果
//异步任务已经得到结果了,才指定回调函数
// setTimeout(() => { #假设异步任务执行需要10秒,这里延时了20秒,此时异步任务已经有结果
// promise.then(successCallback,failureCallback);
// },20000)
</script>
根据上面总结可知,const promise = createAudioFileAsync(audioSettings);
当得到promise对象时,创建音频文件的异步任务已经启动,还没完成
总结
纯回调:必须在启动异步任务前指定
promise:可以在启动异步任务之后指定(此时异步任务还在执行中),也可以过一段时间再指定(假设此时异步任务已经有结果了)
2、promise解决回调地狱问题
- 纯回调函数可能出现回调地狱
<script>
doSomething1(function(result1){
doSomething2(result1,function(result2){
doSomething3(result2,function(result3){
console.log('get final result:',result3)
},failureCallback3)
},failureCallback2)
},failureCallback1)
</script>
doSomething1执行成功后进入成功回调函数并传入result1,doSomething2依赖result1作为参数,执行成功后进入成功的回调函数并传入result2,doSomething3依赖result2作为参数,执行成功后进入成功回调函数并传入result3
代码整体向右发展,不方便阅读,每个函数都要单独做异常处理
- promise方式
<script>
doSomething1()
.then(function(result1){
return doSomething2(result1)
})
.then(function(result2){
return doSomething3(result2)
})
.then(function(result3){
console.log('get final result:',result3)
})
.catch(failureCallback)
</script>
doSomething1()、doSomething2(result1)、doSomething3(result2)
得到的都是promise对象
代码整体是纵向,可阅读性好。所有的then()
只写了成功的回调,任何的失败回调会通过异常传透到最下面的catch
被捕获
- 更优方案,使用async/await
promise虽然没有回调函数嵌套,但是还是存在回调函数,从语法层面去掉回调(虽然编译后是有回调的)
<script>
async function request(){
try{
const result1 = await doSomething1()
const result2 = await doSomething2()
const result3 = await doSomething3()
console.log('get final result:',result3)
}catch(error){
failureCallback(error)
}
}
</script>
网友评论