前言了解一个东西的话, 需要理解它是一个什么玩意, 它的出现解决了什么问题, 在没有 Promise 以前怎么处理的, 在这里纠正一点, Promise 是一种设计模式(1976),前端只是应用了这种设计模式, 而且这种设计模式最初是后端, 前端借鉴的, 下面正式开始
Promise 的用途
Promise的出现是解决前端异步操作的问题, 在没有 Promise 之前, 可能大部分的时候使用回调的方式来处理异步操作, 并且对于 成功或者失败 取名不是很规范
ajax = (method, url, options)=>{
return new Promise((resolve, reject)=>{
const {success, fail} = options
const request = new XMLHttpRequest()
request.open(method, url)
request.onreadystatechange = ()=>{
if(request.readyState === 4){
// 成功就调用 resolve,失败就调用 reject
if(request.status < 400){
resolve.call(null, request.response)
}else if(request.status >= 400){
reject.call(null, request)
}
}
}
request.send()
})
}
这里 Promise 的使用就很简单, return new Promise((resolve, reject) => {}), 五个单词, Promise在这里就声明了 成功是 resolve, 失败是reject, 统一了规范, 而且使用 回调的异步操作对于错误和异常通常不是很好处理
如何使用 Promise.prototype.then
Promise.prototype.then() 是为实例对象 添加处理程序的主要方法. 这个then() 方法接受最多了两个参数: onResolve 处理程序和onReject 处理程序, 都是可选的, 分别对应 成功和失败, 且只能是成功或者失败, 两者互斥
function onResolved(id) {
setTimeout(console.log, 0, id, 'resolved')
}
function onRejected(id) {
setTimeout(console.log, 0, id, 'rejected')
}
let p1 = new Promise(( resolve, reject) => setTimeout(resolve, 3000))
let p2 = new Promise(( resolve, reject) => setTimeout(reject, 3000))
p1.then(() => onResolved('p1'), () => onRejected('p1'))
p2.then(() => onResolved('p2'), () => onRejected('p2'))
// (3s)
// p1 resolved
// p2 rejected
如何使用 Promise.all()
Promise.all() 静态方法创建的promise在一组全部解决之后在解决, 接受一个课迭代对象, 返回一个新的 promise
let p1 = Promise.all([
Promise.resolve(),
Promise.reject()
])
// 可迭代对象中的元素会通过 Promise.resolve()转为新的Promise
let p2 = Promise.all([1,2])
// 空的可迭代对象等价于 Promise.resolve
let p3 = Promise.all([])
//无效的语法
let p4 = Promise.all();
// promise.all 只会在每个promise 都解决了之后在去解决新的Promise
let p = Promise.all([
Promise.resolve(),
new Promise((resolve, reject) => setTimeout(resolve, 1000))
])
setTimeout(console.log, 0, p) // Promise pedding
p.then(() => setTimeout(console.log, 0, 'all() resolved'))
// all() resolved 1s
Promise.race()
Promise.race() 静态方法返回一个包装的 Promise, 是一组Promise中最先解决或者拒绝的 Promise 的 镜像, 这个方法接受一个可迭代对象, 返回一个新的Promise
let p1 = Promise.race([
Promise.resolve(),
Promise.reject()
])
// 可迭代对象中的元素会通过 Promise.resolve() 转为新的 Promise
let p2 = Promise.race([1,2])
//空的可迭代对象等价于 new Promise(() => {})
let p3 = Promise.race([])
// Promise.race() 不会对解决或者解决的 Promise 区别对待, 无论是解决还是拒绝, 只要是第一个解决的, Promise.race() 就会包装其解决值并返回新的Promise
// 解决先发生, 超时后的拒绝背忽略
let p4 = Promise.race([
Promise.resolve(),
new Promise((resolve,reject) => setTimeout(reject, 1000))
])
setTimeout(console.log, 0 ,p4)
// 拒绝先发生, 超时后的解决忽略
let p5 = Promise.race([
Promise.reject(4),
new Promise((resolve, reject) => setTimeout(resolve, 1000))
])
setTimeout(console.log, 0 ,p5)
// 迭代顺序决定了落定顺序
let p6 = Promise.race([
Promise.resolve(5),
Promise.resolve(6),
Promise.resolve(7),
])
setTimeout(console.log, 0, p6)
//如果有一个Promise 拒绝, 只要他是第一个解决的,
//就会成为返回一个新的`Promise` 的理由, 之后在有其他的promise 不会影响 最终的 promise 的结果. 不过, 这并不影响所以包含promise 正常的决绝操作
let p10 = Promise.race([
Promise.reject(3),
new Promise((resolve, reject) => setTimeout(reject, 1000))
])
p1.catch(reason => setTimeout(console.log, 0, reason))