最近学习了下es6新增的Promise,记录下,把promise所涉及到的知识点都总结一遍,为下一篇,手写Promise做铺垫,喜欢的点个赞,谢谢,你们的点赞是我的动力源泉.
Promise是什么?
理解
- 抽象表达:Promise是js中运行异步编程的新的解决方案( 旧的是啥?-->纯回调形式)
- 具体表达:
- 从语法上来说:Promise是一个构造函数
- 从功能上来说:Promise对象用来封装一个异步操作并可以获得其结果
Promise的状态改变
- pending 变为 resolved
- pending 变为 rejected
- 说明:Promise的状态改变只有这2种,且promise对象只能改变一次
- 无论成还是失败,都会有一个结果数据
- 成功结果的数据一般为value,失败结果的数据一般称为reason
promise的基本流程

Promise的基本使用
- 创建一个新的promise对象
- 执行异步操作任务
- 如果成功,调用resolve(value)
- 如果失败,reject(reason)
const p = new Promise((resolve,reject) => {//执行器函数 同步回调
setTimeout(() => {
const time = Date.now();
//如果当前时间是偶数就代表成功,否则即代表失败
if(time%2 == 0){
resolve(`成功了,返回数据time=${time}`)
}else{
reject(`失败了,返回数据time=${time}`)
}
},1000)
})
p.then(
value => {//接收得到成功的value数据 onResolved
console.log(`成功的回调${value}`)
},
reason =>{//接收得到失败的reason数据 onRejected
console.log(`失败的回调${reason}`)
}
)
为什么使用Promise?
指定回调方式更加灵活
- 旧的:必须在启动异步任务前指定回调函数
- Promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数(甚至可以在异步任务结束后指定)
支持链式调用,这个可以解决回调地狱
- 回调地狱是啥:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件
- 回调地狱的缺点:不便于阅读,不便于异常处理
解决方案: Promise链式调用
中间还有 generator/yard 来解决
终极解决方案: async/await
/*对比不同回调方式(伪代码)*/
//成功的回函数
function successCallback(result) {
console.log('声音文件创建成功' + result)
}
//失败的回函数
function failureCallback(error) {
console.log('声音文件创建失败' + error)
}
/* 1.1 纯回调函数 */
//启动任务(audioSettings)前必须指定回调函数(callback)
createAudioFileAsync(audioSettings, successCallback, failureCallback)
//这个咱们可以类比于jQuery的Ajax,在创建请求的时候,
//success于error二个回调函数必须在创建的时候指定,
//不然就没办法处理成功与失败了
/* 1.2 promise */
//可在启动任务(audioSettings)后指定回调函数(callback)
const promise = createAudioFileAsync(audioSettings)
setTimeout(() => {
promise.then(successCallback, failureCallback)
}, 1000)
/* 2.1 回调地狱 */
//回调函数的嵌套
doSomething(function (result) { //第一个函数function就是sucessCallback
doSomethingElse(result, function (newResult) {
doThirdThing(newResult, function (finalResult) {
console.log('Got the final result' + finalResult)
}, failureCallback)
}, failureCallback)
}, failureCallback)
/* 2.2 链式调用 解决回调地狱 但还是有回调的*/
doSomething().then(function(result) { //result是doSomething函数成功执行的返回值
return doSomethingElse(result) //执行器函数,同步回调
})
.then(function(newResult){ //newResult是doSomethingElse成功执行的返回值
return doThirdThing(newResult)
})
.then(function(finalResult){
console.log('Got the final result' + finalResult)
})
.catch(failureCallback) //统一的错误处理 异常传透
/* 2.3 async/await : 回调地狱的终极解决方案 */
//根本上去掉回调函数
async function request() {
try{
const result = await doSomething()
const newResult = await doSomethingElse(result)
const finalResult = await doThirdThing(newResult)
console.log('Got the final result' + finalResult)
} catch (error) {
failureCallback(error)
}
}
如何使用Promise
API
- Promise 构造函数:Promise(excutor){}
- excutor函数:执行器 (resolve,reject)=>{}
- resolve函数:内部定义成功时我们调用的函数 value=>{}
- reject函数:内部定义失败时我们调用的函数reason=>{}
- 说明:excutor会在Promise内部立即同步回调,异步操作在执行器中执行
- Promise.prototype.then方法:(onResolved,onRejected)=>{}
- onResolved函数:成功的回调函数 (value) => {}
- onRejected函数:失败的回调函数 (reason) => {}
- 说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的Promise对象
- Promise.prototype.catch方法:(onRejected)=>{}
- onRejected函数:失败的回调函数 (reason) => {}
- 说明:then()的语法糖,相当于:then(ndefined,onRejected)
- Promise.resolve方法:(value)=>{}
- value:成功的数据或Promise对象
- 说明:返回一个成功或者失败的promise对象
- Promise.reject方法:(reason)=>{}
- reason:失败的原因
- 说明:返回一个失败的promise对象
- Promise.all方法: (promises) => {}
- promises: 包含n个promise的数组
- 说明: 返回一个新的promise, 只有所有的promise都成功才成功,只要有一个失败了就直接失败
- Promise.race方法: (promises) => {}
- promises: 包含n个promise的数组
- 一旦迭代器中的某个promise成功或失败,返回的 promise就会成功或失败(这一点要注意下,平时我们都是回答只要有成功了就返回,其实在有失败的话也会第一时间返回失败的)
- 说明: 返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态
- Promise.allSettled方法:(promises) => {}
- 返回一个在所有给定的promise成功或失败,并带有一个对象数组,每个对象表示对应的promise结果
- 说明,这个api目前还是草案(Draft),有读者在评论区提到这个API,所以晚上就更新了
new Promise( (resolve, reject) => {
setTimeout( () => {
resolve('成功的数据') //resolve就像是一个传递数据的运输机
}, 1000 )
})
.then(
value => {
console.log('onResolved()1', value)
}
)
.catch(
reason => {
console.log('onRejected()1', reason)
}
)
//产生一个成功值为1的Promise对象
const p1 = new Promise((resolve, reject) => {
resolve(1)
})
const p2 = Promise.resolve(2);
const p3 = Promise.reject(3);
p1.then(value => {console.log(value)})
p2.then(value => {console.log(value)})
p3.then(null,reason => {console.log(reason)})
p3.catch(reason => {console.log(reason)})
const pAll = Promise.all([p1,p2,p3]);//会失败因为p3
const pAll = Promise.all([p1,p2]);
pAll.then(
values => {
console.log('all onResolved()', values)
},
reason => {
console.log('all onRejected()', reason)
}
)
const pRace = Promise.race([p1,p2,p3])
pRace.then(
value => {
console.log('race onResolved()', value)
},
reason => {
console.log('race onResolved()', reason)
}
)
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
Promise.allSettled(promises).then(
results => {
console.log(results)
}
);
//下图为console.log结果

promise的几个关键问题
- 如何改变promise的状态? 三种方式去改变状态
- resolve(value):如果当前是pending就会变为resolved
- reject(reason):如果当前是pending就会变为rejected
- 抛出异常:如果当前是pending就会变为rejected
/* 1.error属于promise哪个状态 */ const p = new Promise((resolve, reject)=>{ throw new Error('出错了') //属于reject状态 //throw 3 //抛出异常 promise状态变为rejected失败状态 reason为抛出的3 }) p.then( value => {}, reason => { console.log('reason', reason) } //reason Error: 出错了 //reason: 3 )
- 一个promise指定多个成功/失败回调函数,都会调用吗?
- 当promise改变为对应状态时都会调用
const p = new Promise((resolve, reject)=>{ throw new Error('出错了') //属于reject状态 //throw 3 //抛出异常 promise状态变为rejected失败状态 reason为抛出的3 }) p.then( value => {}, reason => { console.log('reason', reason) } //reason Error: 出错了 //reason 3 ) p.then( value => {}, reason => { console.log('reason2', reason) } ) //这种情况也要注意 p.then( value => {}, reason1 => { console.log('reason1', reason1) } reason1 Error: 出错了 ).then( reason2 => { console.log('reason2', reason2) } //reason2 undefined )
- 改变promise状态和指定回调函数谁先谁后?
- 都有可能,正常情况下是先指定回调函数再改变状态,但也可以先改变状态再指定回调
//正常的:先指定回调函数,后改变状态 new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve(1)//后改变的状态(同时指定数据) 异步执行回调函数 },1000) }),=.then(//先指定回调函数 保存当前指定的回调函数 value => {}, reason => { console.log('reason',reason) } )
- 如何先改变状态再指定回调?
- 在执行器中直接调用resolve()/reject()
//先改变状态,后指定回调函数 new Promise((resolve, reject)=>{ //先改变状态(同时指定数据) resolve(1) }).then( //后指定回调函数,异步执行回调函数 value => { console.log('value', value) }, reason => { console.log('reason', reason) } ) console.log('-----') //先输出----, 再输出value 1
- 延迟更长时间才调用then()
const p = new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve(1) },1000) }) setTimeout(()=>{ p.then( value => { console.log('value', value) }, reason => { console.log('reason', reason) } ) },1200)
- 在执行器中直接调用resolve()/reject()
- 什么时候才能得到数据
- 如果先指定的回调,那么当状态发生改变时,回调函数就会调用,得到数据
- 如果先改变的状态,那么当指定回调时,回调函数就会调用,得到数据
- 都有可能,正常情况下是先指定回调函数再改变状态,但也可以先改变状态再指定回调
- promise.then()返回的新promise的结果状态由什么决定?
- 简单表达:由then()指定的回调函数执行的结果决定
- 详细的说:
- 如果抛出异常,新的rpromise变为rejected,reason为抛出的异常
- 如果返回的是非promise的任意值,新的promise变为resolved,value为返回的值
- 如果返回的是另一个新的promise,此promise的结果就会成为新promise的结果
new Promise((resolve, reject)=>{ resolve(1) }).then( value => { console.log("onResolved1()", value) // 1 //return 2 //新Promise状态为resolved, return得到value值 //return Promise.resolve(3) //返回一个新promise, Promise是函数对象 //return Promise.reject(5) //返回一个新promise, Promise是函数对象 throw 4 //新Promise状态为rejected, throw得到value值 } ).then( value => {console.log("onResolved2()", value)}, reason => {console.log("onRejected2()", reason)} )
- promise如何串联多个操作任务
- promise的then()返回一个新的promise,可以形成then()的链式调用
- 通过then的链式调用串联多个同步/异步任务
new Promise((resolve, reject) => { setTimeout(() => { console.log('执行任务1(异步)') resolve(1) }, 1000) }).then( value => { console.log('任务1的结果', value) console.log('执行任务2(同步)') return 2 } ).then( value => { console.log('任务2的结果', value) return new Promise((resolve, reject) => { //启动任务3(异步) setTimeout(() => { console.log('执行任务3(异步)') resolve(3) }, 1000) }) } ).then( value => { console.log('任务3的结果', value) } )
- promise异常传透
- 当使用promise的then链式调用时,可以在最后指定失败的回调
- 当前任何操作出了异常,都会传到最后失败的回调最后中处理
new Promise((resolve, reject) => { //resolve(1) reject(1) }).then( value => { console.log('onResolved1()', value) return 2 }, //reason => Promise.reject(reason) reason => { throw reason } //默认failureCallback ).then( value => { console.log('onResolved2()', value) return 3 } ).then( value => { console.log('onResolved3()', value) } ).catch(reason => { console.log('onRejected1()', reason) })
- 中断promise链
- 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
- 办法:在回调函数中返回一个pending状态的promise对象
new Promise((resolve, reject) => { reject(1) }).then( value => { console.log('onResolved1()', value) return 2 } ).then( value => { console.log('onResolved2()', value) return 3 } ).then( value => { console.log('onResolved3()', value) } ).catch(reason => { console.log('onRejected1()', reason) return new Promise(()=>{}) //返回一个pending的promise 中断promise链 }).then( value => { console.log('onResolved4()', value) }, reason => { console.log('onRejected4()', reason)} )
总结
Promise知识点是真的挺多的,尤其细节方面的东西,更需要多多思考,多总结,点点滴滴的知识,点个赞,谢谢了,你们的点赞是我的动力源泉.然后争取尽快把手写Promise的文章搞出来.