Promise 链式调用
Promise 对象的then方法会返回一个全新的Promise对象
后面的then方法就是在为上一个then返回的 Promise 注册回调
前面then方法中回调函数的返回值会作为后面then方法回调的参数
如果回调中返回的是Promise,那后面then方法的回调会等待它的结束
Promise 异常处理
注册在window上面
window.addEventListener('unhandledrejection', event => {
const { reason, promise } = event
console.log(reason, promise)
// reason => Promise 失败原因,一般是一个错误对象
// promise => 出现异常的Promise 对象
event.preventDefault()
}, false)
Node当中
process.on('unhandledRejection', (reason, promise) => {
console.log(reason, promise)
// reason => Promise 失败原因,一般是一个错误对象
// promise => 出现异常的 Promise 对象
})
总结:在代码中明确捕获每一个可能的异常(不应该丢给全局统一处理)
Promise 并行执行
var promise = Promise.all([
ajax('api/user.json'),
ajax('api/user.json')
])
promise.then(function (values){
console.log(values)
}).catch(function(error){
console.log(error)
})
// 例子
ajax('/api/url.json')
.then(value => {
const urls = Object.values(value)
const tasks = urls.map(url => ajax(url))
return Promise.all(tasks)
})
.then(values => {
console.log(values)
})
小结: Promise.all等待所有任务结束,Promise.race()只会等待第一个结束的任务
const request = ajax('/api/post.json')
const timeout = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('timeout')), 500)
})
Promise.race([
request,
timeout
])
.then(value => {
console.log(value)
})
.catch(error => {
console.log(error)
})
Promise 执行时序/宏任务 vs. 微任务
// 微任务
console.log('global start')
setTimeout(() => {
console.log('setTimeout')
}, 0)
Promise.resolve()
.then(() => {
console.log(promise)
.then(() => {
console.log(promise2)
.then(() => {
console.log(promise3)
})
console.log('global end')
打印结果:global start / global end / promsie / promise 2 / promise 3 / setTimeout
(假如我正在银行办理存款业务,那办完过后,我突然想办一张信用卡,那这时我会告诉银行柜员,我这个临时需求,而银行的柜员为了提高效率,以及这个客户的体验,不会让我重新上后面排队,那她会捎带一起办理,这种行为不叫插队,我在办完主要任务过程中的一个小插曲,我们在柜台办理业务就像是js回调队列等待执行任务一样,我们排队的人就对应回调队列的每一个任务。回调队列中的任务称之为【宏任务】,宏任务执行过程中可以临时加上一些额外的需求,那这时可以选择作为一个新的宏任务进到队列中排队,也可以作为当前任务的微任务,直接在当前任务结束过后立即执行)
promise的回调会作为微任务执行 微任务:提高整体业务的相应能力
目前绝大多数异步调用都是作为宏任务执行
Promise & MutationObserver还有node里面有一个 process.nextTick 对象 他们都会作为微任务在本轮任务的末尾执行了