這是我參與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
複製代碼