目录大纲
- 初识Promise
- 1)Promise是什么 2)Promise基本用法
- Promise的实例方法
- 1)then() 2)cach 3)finally()
- Promise 的构造函数方法
- 1)Promise.resolve() 2)Peomise.reject() 3)Peomise.all() 4)Promise.race() 5)Promise.allSettled()
- Promise的注意事项以及应用
- 1)Promise注意事项 2)Promise 的应用
一、初识Promise
1、Promise是什么
Promises是异步操作的一种解决方案
认识回调函数:
document.addEventListener('click', () => {
console.log('这是异步函数')
})
console.log('这是同步函数')
2、什么时候使用Promise
Promise 一般用来解决层层嵌套的回调函数(回调地狱 callback hell)的问题
回调地狱问题案例:
const move = (el, { x = 0, y = 0 } = {}, end = () => { }) => {
el.style.transform = `translate3d(${x}px,${y}px,0)`
el.addEventListener('transitionend', () => {
end()
})
}
let BOX = document.getElementById('box')
document.addEventListener('click', () => {
move(BOX, { x: 10 }, () => {
move(BOX, { x: 10, y: 50 }, () => {
move(BOX, { x: 40, y: 50 }, () => {
move(BOX)
})
})
})
})
3、Promise的基本用法
1)、实例化构造函数的生成的实例对象
基本语法
const p = new Promise(() => { })
2)、Promise的状态
Promise的状态一旦变化,就不会变
Promise有3种状态,一开始是pending(未完成),执行resolve,变成fulfilled(resolved),已成功;
执行 reject ,变成rejected ,已失败
const p1 = new Promise((resolve, reject) => {
// Promise有3种状态,一开始是pending(未完成),执行resolve,变成fulfilled(resolved),已成功
// 执行 reject ,变成rejected ,已失败
resolve()
reject()
// Promise的状态一旦变化,就不会变
})
console.log(p1) //Promise {<pending>}=>等待状态
//Promise {<fulfilled>: undefined} =>成功
//Promise {<rejected>: undefined} =>失败
// 3、then方法
3)、resolve() reject() 参数
const p2 = new Promise((resolve, resject) => {
// resolve({name:"HI"})
resject(new Error('失败元婴'))
})
p2.then((res) => {
console.log(res)
}, (res) => {
console.log(res)
})
二、Promise的实例方法
1、then方法
p1.then(() => {
console.log('成功') //成功
}, () => {
console.log('失败')
})
1)、什么时候执行?
pending->fulfilled 时,执行 then的第一个回调函数
pending->rejected 时,执行 then的第二个回调函数
2)、执行后的返回值
then方法执行后返回一个新的Promise对象
const p3 = new Promise((resolve, reject) => {
resolve()
})
p3.then(() => {
}, () => {
}).then(() => {
}, () => { })
3)、then方法返回的Promise对象的状态改变
const p4 = new Promise((resolve, reject) => {
resject(new Error('你失败'))
})
p4.then((res) => { }, () => {
// 在then的回调函数中,return 后面的东西,底层会用Promise包装下,
return { text: '给下一个then使用' }
// 以上写法等同于
return new Promise((resovle, reject) => {
// 默认返回都是成功状态下的Promise对象
resovle({ text: '给下一个then使用' })
})
// 注意如果你需要下一个then走失败:
return new Promise((resolve, reject) => {
reject('需要手动写失败')
})
console.log(res)
}).then((res) => {
console.log('第二个then:', res) //第二个then: {text: "给下一个then使用"}
}, (res) => {
console.log(res) //需要手动写失败
})
个人总结:第一个then,根据Promise决定成功与失败,后续的then方法根据上一个then,决定
后面的then,默认执行的都是成功状态下Promise,需要手动写执行reject
2、使用Promise解决回调地狱问题
const moveTwo = (el, { x = 0, y = 0 } = {}, end = () => { }) => {
el.style.transform = `translate3d(${x}px,${y}px,0)`
el.addEventListener('transitionend', () => {
end()
})
}
let BOX2 = document.getElementById('box2')
const movePromise = ((el, point) => {
return new Promise((resolve, reject) => {
moveTwo(el, point, () => {
resolve();
})
})
})
document.addEventListener('click', () => {
movePromise(BOX2, { x: 150 }).then(() => {
return movePromise(BOX2, { y: 150 })
}).then(_ => {
return movePromise(BOX2, { x: 150 })
})
})
3、catch()
then可以处理成功失败状态,一般then习惯处理成功状态
catch专门用来处理rejected状态
基本用法:
new Promise((resovle, reject) => {
resovle(123)
}).then(_ => {
//throw 简写失败结果
throw new Error('9999')
})
.then((null,err=>{})) // 同下
.catch(err => {
console.log(err)
})
catch()可以捕获它前面的错误,
一般总是建议, Promise对象后面要眼catch方法,这样可以处理Promise内部发生的错误
4、了解finally()
什么时候执行?:当Promise状态发生变化时,不论如何变化都会执行,不变化不执行
本质: finally()本质上是then的特例
new Promise((resovle, reject) => {
reject(11)
}).catch(_ => {
console.log(_)
}).finally(_ => {
// 每次都执行
})
三、 Promise 的构造函数方法
1、Promise.resolve()和Promise.reject()
1)Promise.resolve()是成功状态的一种简写是形式
new Promise(resolve => { })
// 简写:
Promise.resolve('f
2)Promise.resolve参数
一般参数
Promise.resolve('我是成功状态,哈哈哈哈哈哈哈').then(res => { console.log(res) })在这里插入代码片
Promise参数
const pN = new Promise((resolve, reject) => {
// setTimeout(() => {
// resolve('我在1000秒后执行')
// }, 1000);
setTimeout(resolve, 1000, '我在1000秒后执行');
})
Promise.resolve(pN).then(data => {
console.log(data) //我在1000秒后执行
})
// 等同于
pN.then(data => {
console.log(data) //我在1000秒后执行
})
当resolve’函数接收的是Promise对象时,后面的then会根据传递的Promise对象的状态变化决定执行哪一个回调
new Promise(resovle => resovle(pN)).then(data => {
console.log(data) //我在1000秒后执行
})
具有then方法的对象
const thenable = {
then() {
console.log('我是then,在对对象中')
}
}
Promise.resolve(thenable).then(sus => console.log(sus), err => console.log(err))
console.warn(Promise.resolve(thenable), '标记') //Promise {<pending>}[[Prototype]]: Promisecatch: ƒ catch()constructor: ƒ Promise()finally: ƒ finally()then: ƒ then()Symbol(Symbol.toStringTag): "Promise"[[Prototype]]: Object[[PromiseState]]: "pending"[[PromiseResult]]: undefined "标记"
2)Promise.reject()
失败状态Promise的一种简写形式
基本语法:
new Promise((resolve, reject) => {
reject('失败')
})
// 等同于
Promise.reject('失败')
参数:不管什么参数,都会原封不动地向后传递,作为后续方法的参数
const ps = new Promise(resolve => {
setTimeout(resolve, 1000, '我执行l');
})
Promise.reject(ps).catch(err => console.log(ps)) //Promise实例
2、执行流程方法
new Promise((resolve, reject) => {
resolve('哈哈')
}).then(res => {
// 执行成功的三种写法
return '成功'
return new Promise(resolve => resolve('成功'))
return Promise.resovle('成功')
// 执行失败的三种写法
throw '失败'
return new Promise((resolve, reject) => reject('失败'))
return Promise.reject('失败')
})
3、Promise.all()
Promise.all()关注多个Promise对象的的状态变化
传入多个Promise实例,包装成一个新的Promise 实例返回
基本用法
const delay = ms => {
return new Promise(resovle => { setTimeout(resovle, ms); })
}
const all1 = delay(1000).then(() => {
console.log('all1我执行完成:')
return 'all1在all方法中'
})
const all2 = delay(2000).then(() => {
console.log('all2我执行完成:')
throw 'all2在all方法中'
})
Promise.all([all1, all2]).then(res => {
console.log(res) //[ "all1在all方法中","all2在all方法中"]
}).catch(res => console.log('标记', res))
4、Promise.race()
Promise.race() 的状态取决于第一个完成的Promise实例对象如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败(赛跑,谁先执行返回谁)
const delaytwo = ms => {
return new Promise(resovle => { setTimeout(resovle, ms); })
}
const race1 = delaytwo(1000).then(() => {
console.log('race1:')
return 'race1在race方法中'
})
const race2 = delaytwo(2000).then(() => {
console.log('race1')
throw 'race2在race方法中'
})
Promise.race([all1, all2]).then(res => {
console.log(res)
}).catch(res => console.log(res))
5、Promise.allSettled()
- Promise.allSettled()的状态与传入的Promise 状态无关
- 永远都是成功的
- 它只会忠实的记录下各个Promise的表现(结果)
const delaythree = ms => {
return new Promise(resovle => { setTimeout(resovle, ms); })
}
const allSettled1 = delaythree(1000).then(() => {
return 'allSettled1方法成功状态'
})
const allSettle2 = delaythree(2000).then(() => {
throw 'allSettle2方法成功状态'
})
Promise.allSettled([allSettled1, allSettle2]).then(res => {
console.log(res) //(2) [{…}, {…}]
})
四、Promise注意事项以及应用
1、Promise注意事项
* resolve或reject执行后的代码
* Promise.all/race/allSettled的参数问题
* Promise.all/race/allSettled的错误处理
1.resolve或reject函数执行后的代码:推荐在调用resolve或reject函数的时候加上return,不再执行它们后面的代码
new Promise((resolve, reject) => {
return resolve('HHHHH')
})
2.Promise.all/race/allSettled的参数问题//参数如果不是Promise数组, 会将不是Promise的数组元素转变成Promise对象
Promise.all([1, 2, 3]).then(res => console.log(res)) //(3) [1, 2, 3]
//等同于
Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
]).then(res => console.log(res)) //[1, 2, 3]
3、任何可遍历的都可以作为参数
数组、字符串、Set.Map.NodeList.arguments
Promise.all(new Set([1, 2, 3])).then(res => console.log(res)) // [1, 2, 3]
2、Promise应用
图片异步加载
const loadImgAsync = url => {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => { resolve(img) }
img.onerror = () => { reject('图片加载失败') }
img.src = url
})
}
const DOMimg = document.getElementById('img')
loadImgAsync('https://finance-glb-mx.s3.us-west-2.amazonaws.com/upload/pro/i/202108/16301107832998634.jpg ')
.then(res => {
console.log(res,7888888888888888888)
DOMimg.src = res.src
})
.catch(res => console.log(res))