Promise

zfh大约 6 分钟约 1778 字...

为什么要使用 Promise

  1. 指定回调函数的方式更加灵活:
  • 回调函数:必须在启动异步任务前指定
  • promise:启动异步任务 → 返回 promise 对象 → 给 promise 对象绑定回调函数(甚至可以在异步任务结束后指定多个;一个promise指定多个成功/失败回调函数, 状态变化时都会调用)
  1. 支持链式调用,Promise 可以用来解决回调地狱(外部回调函数异步执行的结果是嵌套的回调执行的条件)的问题

Promise 执行流程

promise的基本流程
promise的基本流程

Promise 的基本用法

  1. 实例化Promise构造函数生成实例对象
const p = new Promise((resolve, reject) => {})
  • resolve函数:内部定义成功时调用的函数

  • reject函数:内部定义失败时调用的函数

  1. Promise 对象状态属性

(1)一开始声明后不进行任何操作,就是 pending,未完成

(2)执行 resolve函数,变成fulfilled,已成功

(3)执行reject函数(或抛出异常),变成 rejected,已失败

(4)Promise 函数的两个参数可以任意命名,但是功能并不会改变

(5)Promise 的状态一旦发生变化,就不会再改变,即Promise 函数里的resolve或是 reject 只执行第一个

const p = new Promise((resolve, reject) => {
  // pending->fulfilled
  // resolve(value);     //可以传递参数,在then()方法的第一个回调函数中接收
  // pending->rejected
  // throw '异常信息'
  //reject(reson);        //可以传递参数,在then()方法的第二个回调函数中接收
})

实例方法

Promise.prototype.then()

(1)resolve():状态 pending->fulfilled 的时候,执行 then 方法的第一个回调函数

(2)reject():状态 pending->rejected 的时候,执行 then 方法的第二个回调函数

const p = new Promise((resolve, reject) => {
  // resolve 和 reject 函数的参数
  // resolve('success');  //传的是字符串
  // resolve({ username: 'frank' });  //传的是对象
  reject(new Error('reason')) //传的是错误对象
})
p.then(
  (data) => {
    //data接收的是成功状态下,resolve函数传递的参数
    console.log('success', data)
  },
  (err) => {
    //err接收的是失败状态下,reject函数传递的参数
    console.log('error', err)
  }
)

then 正常返回fulfilledPromise,如果出现异常则返回 rejected状态的Promise

const p = new Promise((resolve, reject) => {
  resolve('frank')
})
p.then((value) => {
  console.log(value) // frank
  // 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
  return 456
}).then((value) => {
  console.log(value) // 456
})
const p = new Promise((resolve, reject) => {
  resolve('frank')
})
p.then((value) => {
  console.log(value)
// 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
  throw '错啦!'
}).then(
  (a) => {
    console.log(a)
  },
  // 执行失败的回调
  (err) => {
    console.log(err)
  }
)
const p = new Promise((resolve, reject) => {
  resolve('frank')
})
p.then((value) => {
  console.log(value)
  // 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
  return new Promise((resolve, reject) => {
    resolve('123')
  })
}).then((value) => {
  console.log(value) // 123
})

Promise.prototype.catch()

  • catch 本质是 then的特例,它只能指定失败的回调,不能指定成功的回调
  • catch 正常返回fulfilledPromise,里面有报错则返回rejected
const p = new Promise((resolve, reject) => {
  reject('err')
})
  .catch((err) => {
    console.log(err)
    return 123
  })
  .then((data) => {
    console.log(data) // 123
  })

Promise.prototype.finally()

finally()方法返回一个 Promise。在 promise 结束时,无论结果是 fulfilled 或者是rejected,都会执行指定的回调函数。这为在 Promise 是否成功完成后都需要执行的代码提供了一种方式

p.finally(function () {
  // 返回状态为(resolved 或 rejected)
})

构造函数方法

Promise.resolve()

Promise.resolve(), 返回一个成功/失败的 Promise 对象的一种简写形式

new Promise((resolve) => resolve('foo'))
// 简写
Promise.resolve('foo')
  • 参数
  1. 一般参数(非 Promise 对象),返回的结果为成功 Promise 对象
Promise.resolve('foo').then((data) => {
  console.log(data)
})
  1. Promise 对象当做参数

如果传入的参数是 Promise 对象,则参数的结果决定了Promise.resolve()的结果

const p = Promise.resolve(
  new Promise((resolve, reject) => {
    reject(123)
  })
)
console.log(p) // Promise {<rejected>: 123}
p.catch((err) => {
  console.log(err)
})

Promise.reject()

Promise.reject(),返回一个失败状态 Promise 对象的一种简写形式

new Promise((resolve, reject) => {
  reject('reason')
})

// 等价于
Promise.reject('reason')

Promise.resolve()不同,Promise.reject()不管什么参数,它返回的结果永远都是失败的,而且传入什么参数,失败的结果就是什么(传入 promise,失败的结果也是 promise)

Promise.all()

传入的 Promise 实例对象所有状态都变成 resolved,最终的状态才会变成 resolved,只要有一个变成 rejected,最终的状态就变成 rejected

基本用法

const delay = (ms) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

const p1 = delay(1000).then(() => {
  console.log('p1 完成了')
  return 'p1'
  // return Promise.reject('reason1');
})

const p2 = delay(2000).then(() => {
  console.log('p2 完成了')
  return 'p2'
  // return Promise.reject('reason2');
})

const p = Promise.all([p1, p2])
p.then(
  (data) => {
    console.log(data) //["p1", "p2"]
  },
  (err) => {
    console.log(err) // 如果都失败,失败结果为第一个失败的Promise的结果
  }
)

Promise.race()

最终状态取决于第一个完成的Promise实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败

const delay = (ms) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

const p1 = delay(1000).then(() => {
  console.log('p1 完成了')

  return 'p1'
  //   return Promise.reject('reason1');
})

const p2 = delay(2000).then(() => {
  console.log('p2 完成了')
  return 'p2'
  // return Promise.reject('reason2');
})

const r = Promise.race([p1, p2])
r.then(
  (data) => {
    console.log(data) // p1
  },
  (err) => {
    console.log(err)
  }
)

Promise.allSettled()

Promise.allSettled() 只会真实记录下各个 Promise 的表现,最终状态永远都是成功的

const delay = (ms) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms)
  })
}

const p1 = delay(1000).then(() => {
  console.log('p1 完成了')

  return 'p1'
  // return Promise.reject('reason');
})

const p2 = delay(2000).then(() => {
  console.log('p2 完成了')

  //   return 'p2';
  return Promise.reject('reason')
})

const allSettledPromise = Promise.allSettled([p1, p2])
allSettledPromise.then((data) => {
  console.log(data)
  //   [
  //     { status: 'fulfilled', value: 'p1' },
  //   { status: 'rejected', reason: 'reason' }
  //   ]
})

Promise.any()

当所有 Promise 实例都变成 rejected 状态,返回的 Promise 才会变成 rejected 状态,参数中只要有一个 Promise 改变为成功状态,则返回的 Promise 状态就是成功的状态:

  1. 参数中只有一个成功状态的Promise实例
// 失败
const p1 = new Promise((resolve, reject) => {
  reject()
})
// 失败
const p2 = new Promise((resolve, reject) => {
  reject()
})
// 成功
const p3 = new Promise((resolve) => {
  resolve('p3成功!')
})
const res = Promise.any([p1, p3, p2])

res.then((value) => {
  console.log(value)
})
  1. 参数中全部是失败状态的 Promise 实例
// 失败
const p1 = new Promise((resolve, reject) => {
  reject()
})
// 失败
const p2 = new Promise((resolve, reject) => {
  reject()
})
// 失败
const p3 = new Promise((resolve, reject) => {
  reject()
})
const res = Promise.any([p1, p3, p2])
res
  .then((value) => {
    console.log(value)
  })
  .catch((err) => {
    console.log(err) // AggregateError: All promises were rejected
    console.log(typeof err) // object
    console.log(err.errors) // ['p1失败', 'p3失败', 'p2失败']
  })
  1. 实际开发中,可能会有这样的需求:一次性加载多张图片,哪一张先加载出来就显示哪一张。那么此时就可以使用 Promise.any()方法实现效果
promise.any()案例
const root = document.querySelector('.root')
// 加载错误
const url1 =
 'https://v.api.aa1.cn/api/api-tx/img/1798ssss.jpg%E5%AE%98%E7%BD%91api.aa1.cn%E5%85%8D%E8%B4%B9%E8%A7%86%E9%A2%91API.jpg'
// 可以加载
const url2 =
  'https://v.api.aa1.cn/api/api-tx/img/1093.jpg%E5%AE%98%E7%BD%91api.aa1.cn%E5%85%8D%E8%B4%B9%E8%A7%86%E9%A2%91API.jpg'
function loadImg(url) {
  const img = new Image(200, 200)
  return new Promise(function (resolve, reject) {
    img.src = url
    img.onload = () => {
      resolve(img)
    }
    img.error = () => {
      throw '图片加载异常,请检查网络'
    }
  })
}
const promiseArr = [loadImg(url1), loadImg(url2)]
Promise.any(promiseArr)
  .then((res) => {
    root.appendChild(res)
  })
  .catch((err) => {
    console.log(err)
  })
<div class="root"></div>
上次编辑于:
本站勉强运行 小时
本站总访问量
網站計數器