ES6 入门第五章
Promise
Promise 是什么?
Promise 是 ES6 引入的异步编程的新解决方案(旧的是谁?旧的解决方案是纯回调函数)。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
用来封装异步操作并可以获取其成功或失败的结果。
Promise的特点
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
Promise 的状态改变
1)pending 变成 fulfilled
2)pending 变成 rejected
说明:只有这两种状态改变情况,且一个Promise对象只能改变一次状态
无论变成成功还是失败,都会有一个结果数据
成功的结果数据一般称为 value ,失败的结果数据一般称为 reason
Promise缺点
- 无法取消
Promise,一旦新建它就会立即执行,无法中途取消。 - 如果不设置回调函数,
Promise内部抛出的错误,不会反应到外部。 - 当处于
pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
Promise 的基本流程
Promise基本使用
步骤:
- 创建一个新的Promise对象
- 执行异步操作任务
- 1 如果成功了,调用resolve(value)
2. 如果失败了,调用reject(reason)
//1. 创建一个新的Promise对象 const p = new Promise((resolve,reject) => {
//执行器函数 //2.执行异步操作任务 setTimeout(() => {
const time = Date.now() //如果当前时间是偶数就代表成功,否则代表失败 if(time % 2 == 0 ){
//3.1如果成功了,调用resolve(value) resolve('成功的数据,time=' + time) } else {
//3.2如果失败了,调用reject(reason) reject('失败的数据,time=' + time) } },1000) }) p.then( value => {
//接收得到成功的value数据 onResolved console.log('成功的回调',value) }, reason => {
//接收得到失败的reason数据 onRejected console.log('失败的回调',reason) } )
讯享网


为什么要用 Promise?
- 指定回调函数的方式更加灵活(灵活指的是时间的问题)
1) 旧的:必须在启动异步任务前指定
2)Promise:启动异步任务 => 返回 Promise 对象 => 给 Promise 对象绑定回调函数(甚至可以在异步任务结束后指定多个)
例子:创建一个音频文件
讯享网//成功的回调函数 function successCallback(result){
console.log("声音文件创建成功:" + result); } //失败的回调函数 function failureCallback(result){
console.log("声音文件创建失败:" + error); }
1)使用纯回调函数
//1. 使用纯回调函数 creatAudioFileAsync(audioSettings, successCallback, failureCallback)
2)使用Promise
讯享网const promise = createAudioFileAsync(audioSettings); setTimeout(()=> {
promise.then(successCallback, failureCallback); },3000)
- 支持链式调用,可以解决回调地狱问题
- 什么是回调地狱?
回调函数嵌套调用(多个串联的异步操作:第一个执行完,再执行第二个……),外部回调函数异步执行的 结果是嵌套的回调执行的条件
//回调地狱 doSomething(function(result){ doSomethingElse(result,function(newResult){ doThirdThing(newResult,function(finalResult){ console.log('Got the final result:' + finalResult) },failureCallback) },failureCallback) },failureCallback) - 回调地狱的缺点?
不便于阅读
不便于异常处理
- 解决方案
Promise链式调用
讯享网
//使用Promise的链式调用解决回调地狱 doSomething() .then(function(result){ return doSomethingElse(result) }) .then(function(newResult){ return doThirdThing(newResult) }) .then(function(finalResult){ console.log('Got the final result:' + finalResult) }) .catch(failureCallback) - 终极解决方案
async/await
// 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
- Promise构造函数:Promise(excutor){}
1)excutor 函数:执行器 (resolve,reject) => {}
2)resolve 函数:内部定义成功时,我们调用的函数 value => {}
3)reject函数:内部定义失败时,我们调用的函数 reason => {}
说明:excutor 会在 Promise 内部立即同步回调,异步操作在执行器中执行
原型方法
1)Promise.prototype.then 方法
2)Promise.prototype.catch 方法
3)Promise.prototype.finally 方法
自身的方法
all()、race()、reject()、resolve()、try()
- Promise.prototype.then 方法 (onResolved, onRejected) => {}
onResolved函数:成功的回调函数 (value) => {}
onRejected函数:失败的回调函数 (reason) => {}
说明:指定用于得到成功value 的成功回调和用于得到失败reason的失败回调
返回一个新的Promise对象
讯享网
new Promise((resolve, reject) => { setTimeout(() => { resolve("成功的数据") //reject("失败的数据") },1000) }).then( value => { console.log('onResolved()1',value) } ).catch( reason => { console.log('onRejected()1',reason) } )

3. Promise.prototype.catch 方法 (onRejected)=> {}
onRejected函数:失败的回调函数 (reason) => {}
说明:then()的语法糖,相当于:then(undefined, onRejected) 或 then(null, onRejected)
new Promise((resolve, reject) => {
setTimeout(() => {
//resolve("成功的数据") reject("失败的数据") },1000) }).then( value => {
console.log('onResolved()1',value) } ).catch( reason => {
console.log('onRejected()1',reason) } )

4. Promise.prototype.finally 方法
用于指定不管 Promise 对象最后状态如何,都会执行的操作。
- Promise.resolve 方法 : (value) => {}
value:成功的数据或Promise对象
作用:将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去 。
说明:返回一个成功/失败的Promise对象
讯享网//产生;一个成功值为1的promise对象 const p1 = new Promise((resolve,reject) => {
resolve(1) }) //语法糖:就是简介语法 const p2 = Promise.resolve(2) console.log(p1) console.log(p2)

6. Promise.reject 方法:(reason) => {}
reason:失败的原因
作用:将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

说明:返回一个失败的Promise对象
//产生;一个失败值为3的promise对象 const p3 = new Promise((resolve,reject) => {
reject(3) }) const p4 = Promise.reject(3) console.log('p3:',p3) console.log('p4:',p4)

讯享网//产生;一个成功值为1的promise对象 const p1 = new Promise((resolve,reject) => {
resolve(1) }) //语法糖:就是简介语法 const p2 = Promise.resolve(2) console.log('p1:',p1) console.log('p2:',p2) const p3 = new Promise((resolve,reject) => {
reject(3) }) const p4 = Promise.reject(3) console.log('p3:',p3) console.log('p4:',p4) p1.then(value => {
console.log(value)}) p2.then(value => {
console.log(value)}) p3.then(null,reason => {
console.log(reason)}) p4.catch(reason => {
console.log(reason)})

7. Promise.all 方法:(promises) => {}
promises:包含n个promise的数组
说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败
const p = Promise.all([p1, p2, p3]);
上面代码中,Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。另外,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
讯享网const p1 = new Promise((resolve,reject) => {
resolve(1) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) const pAll = Promise.all([p1,p2]) console.log('pAll:',pAll) pAll.then( value => {
console.log('all onResolved()',value) }, reason => {
console.log('all onRejected()',reason) } )

const p1 = new Promise((resolve,reject) => {
resolve(1) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) //const pAll = Promise.all([p1,p2]) const pAll = Promise.all([p1,p2,p3]) console.log('pAll:',pAll) pAll.then( value => {
console.log('all onResolved()',value) }, reason => {
console.log('all onRejected()',reason) } )

8. Promise.race 方法 (promises) => {}
promises:包含n个promise的数组
说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态
讯享网const p = Promise.race([p1, p2, p3]);
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
const p1 = new Promise((resolve,reject) => {
resolve(1) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) const pRace = Promise.race([p1,p2,p3]) console.log('pRace',pRace) pRace.then( value => {
console.log('race onResolved()',value) }, reason => {
console.log('race onRejected()',reason) } )

讯享网const p1 = new Promise((resolve,reject) => {
resolve(1) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) //const pRace = Promise.race([p1,p2,p3]) const pRace = Promise.race([p3,p1,p2]) console.log('pRace',pRace) pRace.then( value => {
console.log('race onResolved()',value) }, reason => {
console.log('race onRejected()',reason) } )

状态也不一定是由第一个决定,要看谁先完成,状态就为谁的状态
const p1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve(1) },100) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) const pRace = Promise.race([p1,p2,p3]) console.log('pRace',pRace) pRace.then( value => {
console.log('race onResolved()',value) }, reason => {
console.log('race onRejected()',reason) } )

Promise的几大关键问题
- 如何改变Promise的状态?
(1)resolve(value):如果当前是 pending 就会变成 fulfilled
(2)reject(reason):如果当前是 pending 就会变成 rejected
(3)抛出异常:如果当前是 pending 就会变成 rejected
讯享网
const p = new Promise((resolve,reject) => { //resolve(1) //Promise变成 fulfilled 成功状态 //reject(2) //Promise变成 rejected 失败状态 //throw new Error('出错了') //抛出异常,promise变为rejected失败状态,reason为 抛出的error throw 3 //抛出异常,promise变为rejected失败状态,reason为 抛出的3 }) p.then( value => { }, reason => { console.log('reason',reason)} )

一个 Promise 指定多个成功/失败回调函数,都会调用吗?
当 Promise 改变为对应状态时都会调用
const p = new Promise((resolve,reject) => {
//resolve(1) //Promise变成 fulfilled 成功状态 //reject(2) //Promise变成 rejected 失败状态 //throw new Error('出错了') //抛出异常,promise变为rejected失败状态,reason为 抛出的error throw 3 //抛出异常,promise变为rejected失败状态,reason为 抛出的3 }) p.then( value => {
}, reason => {
console.log('reason',reason)} ) p.then( value => {
}, reason => {
console.log('reason2',reason)} )

- 改变 Promise 状态和指定回调函数谁先谁后?
(1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改状态再指定回调
(2)如何先改状态再指定回调?
1)在执行器中直接调用 resolve()/reject()
2)延迟更长时间才调用 then()
(3)什么时候才能得到数据?
1)如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
2)如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
讯享网
//常规:先指定回调函数,后改变的状态 new Promise((resolve,reject) => { setTimeout(() => { resolve(1) //后改变的状态(同时指定数据),异步执行回调函数 },1000) }).then(//先指定回调函数,保存当前指定的回调函数 value => { console.log('value',value)}, reason => { console.log('reason',reason)} ) /*++++++++++++++++++++++++*/ //如何先改状态,后指定回调函数 new Promise((resolve,reject) => { resolve(1) //先改变的状态(同时指定数据) }).then(//后指定回调函数,异步执行回调函数 value => { console.log('value2',value)}, reason => { console.log('reason2',reason)} ) /*++++++++++++++++++++++++*/ const p = new Promise((resolve,reject) => { setTimeout(() => { resolve(1) //先改变的状态(同时指定数据),异步执行回调函数 },1000) }) setTimeout(() => { p.then( value => { console.log('value3',value)}, reason => { console.log('reason3',reason)} ) },1100) - Promise.then()返回的新的Promise的结果状态由什么决定?
(1)简单表达:由then()指定的回调函数执行的结果决定
(2)详细表达
1)如果抛出异常,新的Promise 变为rejected,reason 为抛出的异常
2)如果返回的是非 Promise的任意值,新的Promise变为resolved,value为返回的值
3)如果返回的是另一个新的Promise,此Promise的结果就会成为新的Promise的结果
new Promise((resolve,reject) =>{ resolve(1) }).then( value => { console.log('onResolved1()',value) }, reason => { console.log('onRejected1()',reason) }).then( value => { console.log('onResolved2()',value) }, reason => { console.log('onRejected2()',reason) } )

讯享网new Promise((resolve,reject) =>{
resolve(1) //reject(1) }).then( value => {
console.log('onResolved1()',value) // return 2 // return Promise.resolve(3) return Promise.reject(5) }, reason => {
console.log('onRejected1()',reason) }).then( value => {
console.log('onResolved2()',value) }, reason => {
console.log('onRejected2()',reason) } )

5. Promise如何串连多个操作任务?
(1)Promise 的then()返回一个新的 Promise,可以开成then()的链式调用
(2)通过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异常传/穿透?
(1)当使用Promise的then链式调用时,可以在最后指定失败的回调
(2)前面任何操作出了异常,都会传到最后失败的回调中处理
讯享网new Promise((resolve,reject) =>{
//resolve(1) reject(1) }).then( value => {
console.log('onResolved1()',value) return 2 }, //reason => {throw reason} ).then( value => {
console.log('onResolved2()',value) return 3 }, //reason => {throw reason} ).then( value => {
console.log('onResolved3()',value) }, reason => Promise.reject(reason) ).catch(reason => {
console.log('onRejected1()',reason) })
执行reject(1)这个函数,因为第一个then()里面没有reason函数,其实默认为reason => {throw reason},所以会一直往下,然后到第二个then(),第二个也没有reason函数,所有到第三个then(),第三个也没有,所有到最后的catch,这就是传/穿透。

6. 中断Promise链?
(1)当使用Promise的then链式调用时,在中间中断,不再调用后面的回调函数
(2)办法:在回调函数中返回一个pending状态的Promise对象
new Promise((resolve,reject) =>{
//resolve(1) reject(1) }).then( value => {
console.log('onResolved1()',value) return 2 }, //reason => {throw reason} ).then( value => {
console.log('onResolved2()',value) return 3 }, reason => {
throw reason} ).then( value => {
console.log('onResolved3()',value) }, reason => Promise.reject(reason) ).catch(reason => {
console.log('onRejected1()',reason) //throw reason //return Promise.reject(reason) return new Promise(() => {
})//返回一个pending的Promise 中断Promise链 }).then( value => {
console.log('onResolved3()',value) }, reason => {
console.log('onRejected2()',reason) } )

如果不想执行catch后面的then了,则用 return new Promise(() => {})中断Promise链,因为此时的状态为pending,既不是fulfilled状态也不是rejected。
async 与 await
async 函数
- 函数的返回值为Promise对象
- Promise对象的结果由async函数执行的返回值决定
讯享网// async 函数的返回值是一个Promise对象 async function fn1() {
return 1 } const result = fn1() console.log(result)

await 表达式
- await 右侧的表达式一般为 Promise对象,但也可以是其它的值
- 如果表达式是Promise对象,await返回的是Promise成功的值
- 如果表达式是其它值,直接将此值作为await的返回值
function fn2() {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(5) },1000) }) } async function fn3() {
const value = await fn2() //await右侧表达式为Promise,得到的结果就是Promise成功的value console.log('value',value) } fn3()

讯享网function fn5() {
return 9 } async function fn3() {
//const value = await fn2() //await右侧表达式为Promise,得到的结果就是Promise成功的value const value = await fn5() //await右侧表达式不是Promise,得到的结果就是它本身 console.log('value',value) } fn3()

注意:
- await必须写在async函数中,但async函数中可以没有await
- 如果await的Promise失败了,就会抛出异常,需要通过try…catch来捕获处理
function fn2() {
return new Promise((resolve,reject) => {
setTimeout(() => {
//resolve(5) reject(6) },1000) }) } async function fn3() {
try{
const value = await fn2() console.log('value',value) } catch (error) {
console.log('得到失败的结果',error) } } fn3()


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/40157.html