翼度科技»论坛 编程开发 JavaScript 查看内容

记录 Promise 的方法

9

主题

9

帖子

27

积分

新手上路

Rank: 1

积分
27
Promise 是异步编程的一种解决方案,比传统的回调函数或事件更合理和更灵活。
Promise 方法

Promise的原型方法:then/catch/finally,这三种方法很常用,then用于处理Promise转为fulfilled状态时的代码,catch用于处理Promise转为rejected状态时的代码(当然then的第二个参数也可处理rejected状态),而finally用于不管Promise状态怎样转换都会最终执行的代码。
promise的then方法的第二个参数和catch方法都可以处理rejected状态,但它们之间有一些区别:

  • then的第二个参数只能处理当前的promise,而catch方法可以处理任意位置的rejected状态。所以,如果多个then方法链式调用中有多个rejected状态,可以在最后使用一个catch方法来处理。
  • then的第二个参数和catch方法的返回值不同。then的第二个参数返回的是一个新的promise对象,而catch方法返回的是一个值或一个新的promise对象。如果返回的是一个值,则会被自动包装成一个resolved状态的promise。
  • catch方法比then的第二个参数更简洁,更易读。因为catch方法只处理rejected状态,而then方法需要在第一个参数中同时处理resolved和rejected状态。
Promise的静态方法: Promise.all、Promise.allSettled、Promise.any、Promise.race、Promise.resolve、Promise.reject。
Promise 静态方法

Promise.resolve和Promise.reject用于一开始就创建 fulfilled或rejected状态的Promise,其他的静态方法传参是Promise实例数组,差异在于处理实例数组的方式和结果。
Promise.all

并行执行多个Promise对象,并在所有Promise对象都成功时返回一个新的Promise对象,其resolve值为一个包含所有Promise结果的数组,如果其中一个Promise对象失败,则返回一个reject的Promise对象,其值为第一个失败的Promise的reject值
  1. ;(async () => {
  2.   const promise1 = Promise.resolve('Hello')
  3.   const promise2 = 42
  4.   // const promise2 = Promise.reject('Error')
  5.   const promise3 = new Promise((resolve, reject) => {
  6.     setTimeout(resolve, 1000, 'Goodbye')
  7.   })
  8.   // const promise4 = Promise.reject('Error2')
  9.   try {
  10.     const result = await Promise.all([promise1, promise2, promise3])
  11.     // 成功输出:[ 'Hello', 42, 'Goodbye' ]
  12.     console.log(result)
  13.   } catch (e) {
  14.     // 失败输出:Error
  15.     console.log(e)
  16.   }
  17. })()
复制代码
Promise.allSettled

并行执行多个Promise对象,返回一个新的Promise对象(状态一定是fulfilled),其resolve值为一个包含所有Promise结果的数组,其中每个元素都是对象,包含Promise对象的状态和结果
  1. ;(async () => {
  2.   const promise1 = Promise.resolve('Hello')
  3.   const promise2 = 42
  4.   // const promise2 = Promise.reject('Error')
  5.   const promise3 = new Promise((resolve, reject) => {
  6.     setTimeout(resolve, 1000, 'Goodbye')
  7.   })
  8.   // const promise4 = Promise.reject('Error2')
  9.   try {
  10.     const result = await Promise.allSettled([promise1, promise2, promise3])
  11.     // 成功输出:
  12.     // [
  13.     //   { status: 'fulfilled', value: 'Hello' },
  14.     //   { status: 'fulfilled', value: 42 },
  15.     //   { status: 'fulfilled', value: 'Goodbye' }
  16.     // ]
  17.     console.log(result)
  18.     // 失败输出:
  19.     // [
  20.     //   { status: 'fulfilled', value: 'Hello' },
  21.     //   { status: 'rejected', reason: 'Error' },
  22.     //   { status: 'fulfilled', value: 'Goodbye' }
  23.     // ]
  24.   } catch(e) {
  25.     // 不会执行
  26.       console.log('error:', e)
  27.   }
  28.   Promise.allSettled([promise1, promise2, promise3]).then((result) => {
  29.     // 成功输出:
  30.     // [
  31.     //   { status: 'fulfilled', value: 'Hello' },
  32.     //   { status: 'fulfilled', value: 42 },
  33.     //   { status: 'fulfilled', value: 'Goodbye' }
  34.     // ]
  35.     console.log(result)
  36.     // 失败输出:
  37.     // [
  38.     //   { status: 'fulfilled', value: 'Hello' },
  39.     //   { status: 'rejected', reason: 'Error' },
  40.     //   { status: 'fulfilled', value: 'Goodbye' }
  41.     // ]
  42.   })
  43. })()
复制代码
Promise.all和Promise.allSettled的区别:

  • Promise.all方法返回的一个Promise对象状态将取决于所有Promise对象的状态。如果其中有任何一个Promise对象被rejected了,那么这个新的Promise对象也会被rejected,并且它的值为第一个被rejected的那个Promise对象的值。
  • Promise.allSettled方法返回的一个Promise对象状态一定是fulfilled。这个返回的Promise对象的值是一个数组,数组中包含了所有Promise对象的状态和值信息。即便其中有任何一个Promise对象被rejected了,也不会影响这个新的Promise对象的状态。
  • 错误处理方面,Promise.all只能捕获处理第一个错误状态,如果需要处理所有状态需要改造(如:每个promise设置catch处理、同步请求/异步等待)或者使用 Promise.allSettled,具体需要怎么做看自己的需求
Promise.any

并行执行多个Promise对象,并返回一个新的Promise对象,其resolve值为第一个成功的Promise对象的resolve值,如果所有Promise对象都失败,则返回一个reject的Promise对象,其值为一个AggregateError对象,其中包含所有Promise对象的reject值。
  1. const promise1 = Promise.reject("error1")
  2. const promise2 = Promise.reject("error2")
  3. const promise3 = Promise.resolve("success")
  4. // const promise3 = Promise.reject("error3")
  5. Promise.any([promise1, promise2, promise3]).then((value) => {
  6.   // 成功输出:success
  7.   console.log(value)
  8. }).catch((error) => {
  9.   // 失败输出:
  10.   // [AggregateError: All promises were rejected] {
  11.   //   [errors]: [ 'error1', 'error2', 'error3' ]
  12.   // }
  13.   console.log(error)
  14. })
复制代码
Promise.race

并行执行多个Promise对象,并返回一个新的Promise对象,其resolve值为第一个完成的Promise对象的resolve值,如果所有Promise对象都失败,则返回一个reject的Promise对象,其值为第一个失败的Promise的reject值。
  1. const promise1 = Promise.reject("error1")
  2. const promise2 = Promise.reject("error2")
  3. const promise3 = Promise.resolve("success")
  4. // const promise3 = Promise.reject("error3")
  5. Promise.race([promise1, promise2, promise3]).then((value) => {
  6.   // 成功输出:error1
  7.   console.log(value)
  8. }).catch((error) => {
  9.   // 失败输出:error1
  10.   console.log(error)
  11. })
复制代码
Promise.race和Promise.any的区别:

  • Promise.race会在其中任意一个Promise对象状态改变(即fulfilled或rejected)时立即返回结果,而Promise.any只会在其中任意一个Promise对象fulfilled时返回结果。
  • 当所有Promise对象都被rejected时,Promise.race会返回被rejected的Promise对象的结果,而Promise.any会抛出AggregateError异常。
  • 如果Promise.race传入的参数是空数组,它会一直处于pending状态,而Promise.any会立即抛出AggregateError异常。(另外:Promise.all和Promise.allSettled返回fulfilled状态)
使用Promise实现站点预检

这是前几天实现的站点预检:判断所有网站链接是否有效,并返回测试的结果。思路:通过get请求测试,考虑请求之间没有关联、错误处理方面最终选择Promise.allSettled,代码如下:
  1. // 实现 对多个网站链接预检,判定网站链接是否有效
  2. import { get } from 'https'
  3. import { get as getHttp } from 'http'
  4. import { URL } from 'url'
  5. import { ATagSites } from '@/type'
  6. export const detectSitesValid = (allSites: ATagSites[]) => {
  7.   // 遍历 allSites 数组,获取所有网站的链接
  8.   const sites: { name: string; url: string }[] = []
  9.   allSites.forEach((aTagSites) => {
  10.     aTagSites.sites.forEach((site) => {
  11.       sites.push({
  12.         name: site.name,
  13.         url: site.link
  14.       })
  15.     })
  16.   })
  17.   // 存储所有网站的请求
  18.   const fetchRequests: Promise<string>[] = []
  19.   // 存储请求结果
  20.   const fetchResults: string[] = []
  21.   // 遍历所有网站,发起请求
  22.   sites.forEach((site) => {
  23.     const { name, url } = site
  24.     const { protocol } = new URL(url)
  25.     const request = protocol === 'https:' ? get : getHttp
  26.     fetchRequests.push(
  27.       new Promise((resolve, reject) => {
  28.         request(
  29.           {
  30.             hostname: new URL(url).hostname,
  31.             path: new URL(url).pathname,
  32.             method: 'GET',
  33.             timeout: 30000
  34.           },
  35.           (res) => {
  36.             const { statusCode, statusMessage } = res
  37.             fetchResults.push(`${name}, ${url}, ${statusCode || 200}, ${statusMessage || 'OK'}`)
  38.             resolve('ok')
  39.           }
  40.         ).on('error', (err) => {
  41.           const { message } = err
  42.           fetchResults.push(`${name}, ${url}, ${0}, ${message}`)
  43.           resolve('error')
  44.         })
  45.       })
  46.     )
  47.   })
  48.   return Promise.allSettled(fetchRequests)
  49. }
复制代码
参考


来源:https://www.cnblogs.com/chenmijiang/p/17314754.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具