promise进化论
1.简单的异步处理初级进化论
console.log(111)
function fn(cb){
setTimeout( () => {
console.log(2222)
},1000)
}
fn()
console.log(3333)
这个是我们一个简单的异步,执行顺序会被打乱,因为fn函数体中出现了setTimeout 定时器,所以下面打印的 33333 会立即执行,不会等待定时器完成以后执行,有的时候我们需要在定时器执行完成以后,然后再执行打印 3333 , 所以我们对函数进行了如下改进
console.log(11111)
function fn(cb){
setTimeout( () => {
consol.log(222)
cb()
})
}
fn(function(){
consol.log(333)
})
我们的改进方案如下: 因为我需要在定时器执行以后然后执行打印 3333 ,所以将 fn 函数 接受一个觅名函数,在执行完打印 222 以后执行觅名函数,我们称途中的 cb 函数为回调函数,在调用 fn 函数的时候传入一个觅名函数,在这个觅名函数体中打印 333 ,现在我们的执行顺序就会如我们所想的执行。。
情景使用
现在我们有如下需求,需要一个方块向右移动200 然后再向下移动200,向左移动200,向上在移动200,最终绕成一个正方形
//封装一个运动函数
function move(ele,arg,target,cb){
// 首先获取在该运动方向上原有的运动距离,
let start = parseInt(window.getComputedStyle(ele,null)[arg])
// 然后将该运动方向上移动距离计算出,然后除以 运动距离的绝对值,如为 1 则是向原有的方向上移动,
// 如果为 -1 则向相反的方向上移动
let dis = (target - start ) / Math.abs(taget - start)
// 设置运动速度
let speed = dis * 5
// 因为需要循环运动,所以下面 fn 为一个递归函数
function fn(){
// 因为每次运动后的样式会发生改变
let now = parseInt(window.getComputedStyle(ele,null)[arg])
// 判断是否等于目标值,
if(now == target){
// 如果当前值等于目标值的话,直接跳出递归执行 cb 函数
cb && cb()
}else{
// 如果不等于继续执行回调
/// 把当前的属性值加上上次的值,然后赋值给计算样式,
ele.style[arg] = now + speed + 'px'
//requestAnimationFrame 是一个执行动画,传入一个函数,会执行该函数,会根据单奶
window.requestAnimationFrame(fn)
}
}
// 执行fn函数
fn()
}
// 获取元素
let ele = document.querySelector(".box")
// 按照执行顺序依次在执行,如不在回调函数中执行,会发生同时执行两个函数,得不到理想的结果。。
move(ele,'left',200,funcion(res){
move(ele,"top",200,function(res){
move(ele,"left",0,function(res){
move(ele,"top",0,function(res){
consol.log(res)
})
})
})
})
2.promise的中级进化
proimse 是一个异步处理函数,
promise的三中状态: 1.pengding(没有返回值的状态) 2.resolved (返回值为正确的状态) 3. rejected (返回值为错误的时候的状态)
fucntion fn(){
return new Promise( (resolved,regected) = {
// 如果返回为一下,则为正确状态
resolved('success')
// 如返回如下则为 错误状态,并且会向控制台抛出一个错误
rejected('error')
})
}
// 如promise的状态为resolved 则 会执行.then 后的第一个函数,如为rejcted 状态,则会执行第二个函数,
fn().then( res => {
console.log(res)
},(err) => {
console.log(err)
})
then回调方法的三种回调状态,
1.不返回,默认返回一个状态为 resolved状态的promise 的对象
2.返还非promise对象;,默认返还状态为 resolved状态 的 promise对象,并把参数携带到promise对象的值中。
3.直接 return promise 对象
将上述场景进行改造
function move(ele,arg,target){
// 将该函数封装为promise 对象并返回出去
return new Promise( (resolve,reject) => {
let start = parseIInt(window.getComputedStyle(ele,null)[arg])
let dis = (target - start ) / Math.abs(target - start)
let speed = dis *5
function fn(){
let now = parseInt(window.getComputedStyle(ele)[arg])
if(now === target){
console.log('运动完成')
// 如果 目标值等于当前值, promise 函数结束,状态为resolved 的状态 结束
resolved('运动完成')
}else {
ele.style[arg] = now + speed + "px"
window.requestAmintionFrame(fn)
}
}
fn()
} )
}
let ele = document.querySelector('.box')
move(ele,'left',200).then(res => {
return move(ele,"top",200)
}).then(res => {
return move(ele,"left",0)
}).then(res => {
return move(ele,"top",0)
}).then( res => {
console.log(res)
})
和上次比较,增加了可读性和增加了更多的逻辑性
promise 的其他方法
1.Promise.resolved
let p1 = promise.resolved()
console.log(p1)
此时p1为一个状态为 resolved 状态的 Promise 对象
2.Promise.reject
let p1 = promise.reject()
console.log(p1)
此时p1为一个状态为 reject 状态的 Promise 对象
1.Promise.all
// p1 , p 2 ,p 3 为promise对象并且都是resolved状态
let p = promise.all([p1,p2,p3])
p.thne(res => {
console.log(res)
})
打印结果为 一个数组,数组中为每项的返回值
当有一个执行错误都不会有执行结果
1.Promise.race
let p1 = promise.race([p1,p2,p3])
p1.then(res => {
console.log(res)
})
p1,p2,p3 三项哪个返回最快,打印的为哪个的返回值
async函数和 await 的终极进化Promise
async 是写在函数function的前面 声明这是一个异步函数
await 写在promise的前面,表示异步等待
async 和 await 必须配合使用
async function mufn(){
try{
await new Promise( (resolved , rehect) => {
setTimeout( () => {
console.log(111111111111)
resolve('success)
},1000)
} )
await new Promise((resolved,reject) => {
setTimeout( () => {
console.log(111111111111)
resolved(;sucess)
},2000)
})
await new Promise((resolved,reject) => {
setTimeout( () => {
console.log(3333333333)
resolved(;sucess)
},1000)
})
}catch(err){
console.log(err)
}
}
因为使用异步等待 await、所以总执行时间为 6000 毫秒
上述函数改进的终极进化
/// 上述的 move函数和ele 获取不动,,
async function fn(){
try{
await move(ele,'left',200)
await move(ele,'top',200)
await move(ele,'left',0)
await move(ele,"top",0)
}catch(err){
console.log(err)
}
}