解析 Promise 的本质 和用法

386 阅读3分钟

前言了解一个东西的话, 需要理解它是一个什么玩意, 它的出现解决了什么问题, 在没有 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))