什么是Promise?
1、抽象表达:是JavaScript中进行异步编程的新的解决方案(旧的指的是纯回调式的用法)。
2、具体表达:
(1)从语法上来说:promise是一个构造函数
(2)从功能上来说:promise对象用来封装一个异步操作并且可以获取其结果
Promise的状态改变
promise一共有三个状态:pending、resolved、rejected。
1、pending变为resolved
2、pending变为rejected
说明:pending变化的状态只有这俩种,且一个promise对象只能改变一次,无论变为成功还是失败,都只会有一个结果数据,成功的结果数据一般称为value,失败的数据结果一般称为reason。
promise操作流程图
写一个基本的promise操作:
/*
简单的promise操作流程:
1、创建一个新的promise对象
2、执行一个异步任务
3、判断异步操作成功与否:
3.1、成功:调用resolve(value)
3.2、失败:调用reject(reason)
*/
const p = new Promise((resolve,reject) =>{ // 创建一个新的promise对象 ,相当于一个执行器函数// 执行一个异步操作任务
setTimeout(() => {
const time = Date.now() // 生成一个现在的时间
if (time %2 == 0) {
// 表示成功,调用resolve(value)
resolve("成功的数据是 "+time)
} else {
// 表示失败,调用reject(reason)
reject('失败的数据是 '+time)
}
},1000)
})
p.then(
value => { //接收得到成功的数据
console.log('成功的回调 ' + value)
},
reason => { //接收得到失败的数据
console.log('失败的回调' + reason)
}
)
为什么要用Promise
指定回调函数的方式更灵活
1、旧的:必须在启动异步任务之前指定。
2、promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
例1——纯回调函数实现
// 使用纯回调函数实现一个回调
function successCallback(result){ //手动创建一个成功的回调函数
console.log('声音文件创建成功:' + result)
}
function failureCallback(error){
console.log('声音文件创建失败:' + error)
}
createAudioFileAsync(audioSetting,successCallback,failureCallback) //创建一个创建音频的异步任务
/*
1、使用纯回调函数首先要定义好俩个回调函数再去启动异步任务
如果使用promise的话,指定回调函数的方式更加灵活,不一定要在执行器函数之前就设置回调函数,可以在启动异步任务之后,甚至可以在有了结果之后再设定回调函数
*/
支持链式调用,可以解决回调地狱问题
1、什么是回调地狱?
多个串联的异步操作,就会出现回调地狱,通常还以上个回调函数的结果进行处理
回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
2、回调地狱的缺点
不方便阅读,不方便异常处理
例:简单的地狱回调的形式
doSomething(function(result){ //这个函数调用后结果为result,传给下一层函数
doSomethingElse(result,function(newResult){ //把上层的result作为条件,再指定成功的回调和失败的回调成功的回调会生成全新的结果newResultdoThirdThing(newResult,function(finalResult){ //把上层成功回调的结果再拿来当做条件,给他设置成功回调和失败回调
console.log('回调地狱的简单模板,多个异步操作串联')
},failureCallback)
},failureCallback)
},failureCallback)
采用promise的链式调用解决回调地狱问题
优点:1、代码可阅读性高
2、统一异常处理,异常处理方便
// 采用promise的链式调用解决回调地狱
doSomething() // 得到promise对象,启动异步任务(一个promise对应一个异步任务)
.then(function(result){ //成功的回调result,调用第二个异步任务,返回一个新的promise
return doSomethingElse(result) //把这个result结果作为成功传递给下一层的异步任务
})
.then(function(newResult){ //获取到doSomethingElse的成功回调newResult,并且继续向下传递
return doThirdThing(newResult)
})
.then(function(finalResult){ //获取到doThirdThing的成功回调finalResult
console.log('使用promise的链式形式解决回调地狱') // final成功回到的结果
})
.catch(failureCallback) // 统一处理异常,称为异常传透
3、解决方案
async/await
使用async/await解决终极解决回调地狱的问题
async function request(){
try{
const result = await doSomething()
const newResult = await doSomethingElse(result)
const finalResult = await doThirdThing(newResult)
console.log('用async/await终极解决回调地狱问题'+ result + newResult + finalResult)
} catch(error){
console.log(error)
}
}
Promise的API(语法)
1、Promise构造函数:promise(excutor){}
excutor函数:同步执行(resolve,reject) => {} 执行器函数
resolve函数:内部定义成功时我们调用的函数 value => {}
reject函数:内部定义失败时我们调用的函数 reason => {}
说明:excutor(执行器函数)会再Promise内部立即同步回调,异步操作在执行器中执行
2、Promise.prototype.then方法:(onResolved,onRejected) => {}
onResolved函数:成功的回调函数 (value) => {}
onRejected函数:失败的回调函数 (reason) => {}
说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调。
返回一个新的promise对象
3、Promise.prototype.catch方法:(onRejected) => {}
onRejected函数:失败的回调函数(reason) => {}
说明:then()的语法糖,相当于:then(undefined,onRejected)
4、Promise.resolve方法: (value) => {}
value:成功的数据或promise对象
说明:返回一个成功/失败的promise对象
5、Promise.reject方法:(reason) => {}
reason:失败的原因
说明:返回一个失败的promise对象
6、Promise.all方法:(promise) => {}
promise:包含n个promise的数组
说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败就直接失败
7、Promise.race方法:(promise) => {}
promises:包含n个promise的数组
说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态
Promise的异常抛出
promise也可以使用异常抛出,抛出后promise的状态为rejected
const p = new Promise((resolve,reject) => {
// resolve(1) promise变为resolved成功的返回状态
// reject(2) promise变为rejected失败的返回状态
// throw new error('出错了') 抛出异常,promise变成rejected失败状态,reason为 抛出的异常
throw 3
})
p.then(
value => {
},
reason => {
console.log('reason ' + reason)
}
)
promise状态和指定回调函数先后问题
(1)都有可能,正常情况下时先指定回调再改变状态,但也可以先改变状态再去指定回调
(2)如何先改变状态再指定回调?
1、在执行器中直接调用resolve()/reject()
2、延迟更长时间才调用then()
(3)什么时候才能得到数据
1、如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
2、如果先改变状态,那当指定回调时,回调函数就会调用,得到数据
例:先指定回调函数,后改变状态值
new Promise((resolve,reject) => {
setTimeout(() => {
reject(1) // 后改变状态(同时指定数据),异步执行回调函数
},1000)
}).then( // 先指定回调函数,保存当前指定的回调函数
value => {},
reason => {console.log('reason', reason)}
)
例:先改变状态值,后指定回调函数
new Promise((resolve, reject) => {
resolve(1) // 先改变的状态(同时指定数据)
}).then( // 后指定回调函数,异步执行回调函数
value => {
console.log('value2',value)
}
)
Promise.then()返回的新的promise的结果状态由什么决定?
(1)简单表述:由then()指定的回调函数执行的结果决定
(2)详细表达:
1、如果抛出异常,新promise变为rejected,reason为抛出的异常
2、如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
3、如果返回的是另一个新promise,次promise的结果就会成为新promise的结果
Promise异常传透
(1)当使用promise的then链式调用时,可以在最后指定失败的回调
(2)当前面任何操作出了异常,都会传到最后的回调中处理
中断promise链
(1)当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数
(2)办法:在回调函数中返回一个pendding状态的promise对象
自定义(手写)promise
才艺展示级别,学不会了,等啥时候我觉的我行了我再来学学看!