Promise:问题与应用

问题导向

Promise是什么? 如何使用?

如果你都有了答案,可以忽略本文章,或去JS学习地图寻找更多答案


Promise问题

问:一个Promise指定多个成功/失败回调,都会调用吗?
答:都会调用


问:改变Promise状态和指定回调函数谁先谁后?
答:都有可能,正常情况下先指定回调再改变状态,也可以先改变状态再指定回调
问:如何先改变状态,再指定回调?
答:在执行器中调用resolve/reject,将Promise对象赋值给变量,再.then调用
问:什么时候才能得到数据?
答:如果先指定的回调,当状态改变时,回调就出触发,得到数据
   如果先改变的状态,当指定回调时,回调才会触发,得到数据
   
   
问:Promise.then()返回的新promise的结果状态由什么决定?
答:由then指定的回调函数执行的结果决定,
    如果抛出异常,新promise变为rejected,被失败回调捕获
    如果任何的是非promise的任意值,新promise变为resolved,value为成功回调中的值
    如果返回的是另一个新的promise,此promise的结果就会变为新的promise
    注意:
    1.then的成功回调,没有返回任何值,新promise的成功回调获取到是undefined
    2.then的失败回调,如果没有任何值,等于返回undefined,
    新promise是resolved状态,成功回调获取到是undefined
    
    
问:Promise如何串联多个操作任务?
答:Promise的then返回一个新的promise,可以根据状态链式调用,
    串联多个任务,同步异步都可以,但异步必须包在promise里面
    
    
问:Promise的异常传透?(错误统一处理)
答:当使用Promise的then链式调用时,可以在最后指定失败的回调,统一处理


问:中断Promise链?
答:当使用promise的then链式调用时,在中间中断,不在执行后面的回调函数
    方法:在回调中返回一个pending状态的promise对象

执行顺序问题

第一题:

setTimeout(() => {
    console.log(1)
},0)
new Promise((resolve) => { //excutor马上会执行
    console.log(2)
    resolve()
}).then(() => {
    console.log(3)
}).then(() => {
    console.log(4)
})
console.log(5)

执行顺序:2 5 3 4 1
同:2 5
宏:[1]
微:[3]先执行3,才放4进微任务,因为没执行的时候是pending状态

第二题:

const first = () => new Promise((resolve,reject) => {
    console.log(3)
    let p = new Promise((resolve,reject) => {
        console.log(7)
        setTimeout(() => {
            console.log(5)
            resolve(6) //不执行,因为状态不是pending
        },0)
        resolve(1)
    })
    resolve(2)
    p.then((arg) => {
        console.log(arg)
    })
})
first().then((arg) =>{
    console.log(arg)
})
console.log(4)

执行顺序:3 7 4 1 2 5
同:3 7 4
宏:[5]
微:[1, 2]

第三题:

重点:同层then的同步代码必须执行完,才会把下一个then的回调放到队列中

setTimeout(() => {
    console.log(0)
},0)
new Promise(resolve,reject => {
    console.log(1)
    resolve()
}).then(() => {  //#1
    console.log(2)
    new Promise(resolve,reject => {
        console.log(3)
        resolve()
   }).then(() => { //##1
       console.log(4)
   }).then(() => {
       console.log(5)
   })
}).then(() => { //因为这个回调的结果依赖于上一个,不执行完上一个,不会执行
    console.log(6)
})

new Promise(resolve,reject => {
   console.log(7)
}).then(() => {
   console.log(8)
})

执行顺序:1 7 2 3 8 4 6 5 0
同:1 7 
异同:3
宏:[0]
微:[2 8 4 6]

头条面试题

async function async1(){
   console.log('async1 start')  //2
   await async2() //回调=微
   console.log('async1 end') // 6
}async function async2(){
   console.log('async2')  //3
}
​
console.log('script start')  //1settimeout(function(){   //宏任务
   console.log('settimeout')  //8
},0)async1()new Promise(function(resolve){
   console.log('promise1') // 4
   resolve()
}).then(function(){//异微
   console.log('promise2')  //7
})
​
console.log('script end')  //5

其他

Promise.resolve().then(() => { //then返回resolved
    console.log(1) //1
}).catch(() => {   //不执行
    console.log(2)
}).then(() => {    //执行
    console.log(3) //3
})




Promise.resolve().then(() => { //then返回rejected
    console.log(1) //1
    throw new Error('error1')
}).catch(() => {   //执行2,返回resolved
    console.log(2) 
}).then(() => {    //执行3
    console.log(3) 
})




Promise.resolve().then(() => { //then返回rejected
    console.log(1) //1
    throw new Error('error1')
}).catch(() => {   //执行2,返回resolved
    console.log(2) 
}).catch(() => {    //catch不执行
    console.log(3) 
})

应用

加载一张图片

function loadImg(url){
   return new Promise((resovle,reject) => {
       const img = new Image()
       img.src = url
       img.onload = () => {
           resolve(img)
       }
       img.onerror = () => {
           reject(new Error(`图片加载失败 ${src}` ))
       }
  })
}

如果失败则显示一张其他的图片
let url = './lunbotu12.jpg'
let errorUrl = './lunbotu2.jpg'

loadPic(url).then(res => {
    document.body.appendChild(res)
}).catch((err) => {
    let pic = new Image()
    pic.src = errorUrl
    document.body.appendChild(pic)
}).finally(() => {
	console.log('加载完成')
})

批量获取数据

function getUser(names){
   let promises = names.map(name => {
  		return ajax(`xxx${name}`)
	})
   return Promise.all(promises)
}

getUser(['大神','乔伊']).then(users => {
   console.log(users)
})

加载图片,三张加载完再显示到页面中

function loadImg(url){
   return new Promise((resovle,reject) => {
       const img = new Image()
       img.src = url
       img.onload = () => {
           resolve(img)
       }
       img.onerror = () => {
           reject(new Error(`图片加载失败 ${src}` ))
       }
  })
}

let p1 = loadImg('地址')
let p2 = loadImg('地址')
let p3 = loadImg('地址')
let result = Promise.all([p1,p2,p3])

result.then(res => {
   console.log(res)
   result.forEach(item => {
       document.body.appendChild(item)
  })
},err => {
   console.log(err)
})

每隔2秒输出一个user

async function sleep(dalay = 2000){
   return new Promise(resovle => {
       setTimeout(()=>{
           resovle()
      }, dalay)
  })
}async function show(){
   for(const user of ['大神','乔伊']){
       await sleep()
       console.log(user)
  }
}show()

学习更多

JS学习地图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值