这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战node
const p=new Promise((resolve,reject)=>{
if(...){
reject(new Error())
}
resolve(100)
})
p.then((val)=>{
console.log(val) // 100
},(err)=>{
console.log('rejected',err)
})
复制代码
function ajax(url){
return new Promise((res,rej)=>{
const xhr=new XMLHttpRequest()
xhr.open('GET',url)
xhr.onload=function(){
if(this.status===200){
resolve(this.response)
}else{
reject(new Error(this.statusText))
}
}
xhr.send()
})
}
ajax('api/a/b.json').then((res)=>{
console.log(res)
},(err)=>{
console.log(err)
})
复制代码
每个then方法都是在为上一个then返回状态明确的回调。Promise的then方法会返回一个全新的promise对象。then方法里,若是返回一个肯定的简单值如'aa',能够视为return Promise.resolve('aa')
。若是没有返回值则视为返回Promise.resolve(undefined)
。后面的then方法就是在为上一个then返回的Promise注册回调,前面的then方法中回调函数的返回值会做为后面的then方法回调的参数,若是回调中返回的是promise对象,后面的then方法的回调会等待它的决议。面试
then方法中的异常捕获和promise.catch有很大不一样,看下面代码ajax
const p=()=>=new Promise(....)
p() //1
.then(()=>{},(err)=>{
// 只能捕获到1处的异常
})
p()//1
.then(()=>{}) //2
.catch(err=>{
// 一、2处的异常均可以捕获
})
复制代码
promise上的任何异常都会向后传递直至捕获。json
能够注册unhandledrejection事件来捕获未被定义的异常api
window.addEventListener('unhandledrejection',event=>{
const {reason,promise}=event
console.log(reason,promise)
// reason失败缘由,promise失败对象
event.preventDefault();
},false)
复制代码
同理,对于node环境:promise
process.addEventListener('unhandledrejection',(reason,promise)=>{
console.log(reason,promise)
// reason失败缘由,promise失败对象
})
复制代码
const promise1=ajax('/api/....')
const promise2=Promise.resolve(promise)
promise1===promise2 // true
复制代码
Promise.resolve({
then:(onFullfilled,onRejected)=>{
onFullfilled('foo')
}
})
.then(val=>{
console.log(val) // foo
})
复制代码
Promise.all(Array)等待全部的任务都成功结束才会成功结束,只要有一个任务失败,这个promise就会以失败结束markdown
竞争态,只会返回第一个结束的任务。异步
宏任务能够选择做为一个新的宏任务进到队列中排队,也能够做为当前任务的微任务,直接在当前任务结束事后当即执行,而不是到整个消息队列中从新排队。目前大多数异步调用都是做为宏任务执行函数
宏任务:setTimeout、setInterval、requestAnimationFrameoop
微任务:promise回调,MutationObserver,process.nextTick
一道面试题:
setTimeout(_ => console.log(4))
new Promise(resolve => {
resolve()
console.log(1)
}).then(_ => {
console.log(3)
})
console.log(2)
复制代码
打印 一、二、三、4。4先进入消息队列(宏任务),promise实例化是同步代码,因此按照顺序先执行1,promise的回调3是异步放入消息队列(微任务),以后同步下来打印2.eventloop启动,先执行微任务,打印3,执行宏任务打印4.
const macroTaskList = [
['task1'],
['task2', 'task3'],
['task4'],
]
for (let macroIndex = 0; macroIndex < macroTaskList.length; macroIndex++) {
const microTaskList = macroTaskList[macroIndex]
for (let microIndex = 0; microIndex < microTaskList.length; microIndex++) {
const microTask = microTaskList[microIndex]
// 添加一个微任务
if (microIndex === 1) microTaskList.push('special micro task')
// 执行任务
console.log(microTask)
}
// 添加一个宏任务
if (macroIndex === 2) macroTaskList.push(['special macro task'])
}
// > task1
// > task2
// > task3
// > special micro task
// > task4
// > special macro task
复制代码