记录 Promise 的方法

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

Promise 方法

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

promise的then方法的第二个参数和catch方法都可以处理rejected状态,但它们之间有一些区别:

  1. then的第二个参数只能处理当前的promise,而catch方法可以处理任意位置的rejected状态。所以,如果多个then方法链式调用中有多个rejected状态,可以在最后使用一个catch方法来处理。

  2. then的第二个参数和catch方法的返回值不同。then的第二个参数返回的是一个新的promise对象,而catch方法返回的是一个值或一个新的promise对象。如果返回的是一个值,则会被自动包装成一个resolved状态的promise。

  3. 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用于一开始就创建 fulfilledrejected状态的Promise,其他的静态方法传参是Promise实例数组,差异在于处理实例数组的方式和结果。

Promise.all

并行执行多个Promise对象,并在所有Promise对象都成功时返回一个新的Promise对象,其resolve值为一个包含所有Promise结果的数组,如果其中一个Promise对象失败,则返回一个reject的Promise对象,其值为第一个失败的Promise的reject值

;(async () => {
  const promise1 = Promise.resolve('Hello')
  const promise2 = 42
  // const promise2 = Promise.reject('Error')
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'Goodbye')
  })
  // const promise4 = Promise.reject('Error2')

  try {
    const result = await Promise.all([promise1, promise2, promise3])
    // 成功输出:[ 'Hello', 42, 'Goodbye' ]
    console.log(result)
  } catch (e) {
    // 失败输出:Error
    console.log(e)
  }
})()

Promise.allSettled

并行执行多个Promise对象,返回一个新的Promise对象(状态一定是fulfilled),其resolve值为一个包含所有Promise结果的数组,其中每个元素都是对象,包含Promise对象的状态和结果

;(async () => {
  const promise1 = Promise.resolve('Hello')
  const promise2 = 42
  // const promise2 = Promise.reject('Error')
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'Goodbye')
  })
  // const promise4 = Promise.reject('Error2')

  try {
    const result = await Promise.allSettled([promise1, promise2, promise3])
    // 成功输出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'fulfilled', value: 42 },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
    console.log(result)
    // 失败输出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'rejected', reason: 'Error' },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
  } catch(e) {
    // 不会执行
      console.log('error:', e)
  }

  Promise.allSettled([promise1, promise2, promise3]).then((result) => {
    // 成功输出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'fulfilled', value: 42 },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
    console.log(result)
    // 失败输出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'rejected', reason: 'Error' },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
  })
})()

Promise.all和Promise.allSettled的区别:

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

Promise.any

并行执行多个Promise对象,并返回一个新的Promise对象,其resolve值为第一个成功的Promise对象的resolve值,如果所有Promise对象都失败,则返回一个reject的Promise对象,其值为一个AggregateError对象,其中包含所有Promise对象的reject值。

const promise1 = Promise.reject("error1")
const promise2 = Promise.reject("error2")
const promise3 = Promise.resolve("success")
// const promise3 = Promise.reject("error3")

Promise.any([promise1, promise2, promise3]).then((value) => {
  // 成功输出:success
  console.log(value)
}).catch((error) => {
  // 失败输出:
  // [AggregateError: All promises were rejected] {
  //   [errors]: [ 'error1', 'error2', 'error3' ]
  // }
  console.log(error)
})

Promise.race

并行执行多个Promise对象,并返回一个新的Promise对象,其resolve值为第一个完成的Promise对象的resolve值,如果所有Promise对象都失败,则返回一个reject的Promise对象,其值为第一个失败的Promise的reject值。

const promise1 = Promise.reject("error1")
const promise2 = Promise.reject("error2")
const promise3 = Promise.resolve("success")
// const promise3 = Promise.reject("error3")

Promise.race([promise1, promise2, promise3]).then((value) => {
  // 成功输出:error1
  console.log(value)
}).catch((error) => {
  // 失败输出:error1
  console.log(error)
})

Promise.race和Promise.any的区别:

  1. Promise.race会在其中任意一个Promise对象状态改变(即fulfilled或rejected)时立即返回结果,而Promise.any只会在其中任意一个Promise对象fulfilled时返回结果。

  2. 当所有Promise对象都被rejected时,Promise.race会返回被rejected的Promise对象的结果,而Promise.any会抛出AggregateError异常。

  3. 如果Promise.race传入的参数是空数组,它会一直处于pending状态,而Promise.any会立即抛出AggregateError异常。(另外:Promise.all和Promise.allSettled返回fulfilled状态)

使用Promise实现站点预检

这是前几天实现的站点预检:判断所有网站链接是否有效,并返回测试的结果。思路:通过get请求测试,考虑请求之间没有关联、错误处理方面最终选择Promise.allSettled,代码如下:

// 实现 对多个网站链接预检,判定网站链接是否有效

import { get } from 'https'
import { get as getHttp } from 'http'
import { URL } from 'url'

import { ATagSites } from '@/type'

export const detectSitesValid = (allSites: ATagSites[]) => {
  // 遍历 allSites 数组,获取所有网站的链接
  const sites: { name: string; url: string }[] = []
  allSites.forEach((aTagSites) => {
    aTagSites.sites.forEach((site) => {
      sites.push({
        name: site.name,
        url: site.link
      })
    })
  })

  // 存储所有网站的请求
  const fetchRequests: Promise<string>[] = []
  // 存储请求结果
  const fetchResults: string[] = []

  // 遍历所有网站,发起请求
  sites.forEach((site) => {
    const { name, url } = site
    const { protocol } = new URL(url)
    const request = protocol === 'https:' ? get : getHttp
    fetchRequests.push(
      new Promise((resolve, reject) => {
        request(
          {
            hostname: new URL(url).hostname,
            path: new URL(url).pathname,
            method: 'GET',
            timeout: 30000
          },
          (res) => {
            const { statusCode, statusMessage } = res
            fetchResults.push(`${name}, ${url}, ${statusCode || 200}, ${statusMessage || 'OK'}`)
            resolve('ok')
          }
        ).on('error', (err) => {
          const { message } = err
          fetchResults.push(`${name}, ${url}, ${0}, ${message}`)
          resolve('error')
        })
      })
    )
  })

  return Promise.allSettled(fetchRequests)
}

参考

原文链接:https://www.cnblogs.com/chenmijiang/p/17314754.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:记录 Promise 的方法 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • js获取 gif 的帧数的代码实例

    下面是如何通过JavaScript获取gif图片的帧数的完整攻略: 获取gif的帧数 在JavaScript中获取gif的帧数,可以使用Image对象的onload事件,通过遍历每一帧来获取gif的帧数。具体步骤如下: 创建一个Image对象。 将src属性设置为gif图片的URL地址。 在Image对象上注册onload事件回调函数。 在回调函数中,可以通…

    JavaScript 2023年6月11日
    00
  • html嵌入javascript代码的三种方式

    HTML嵌入JavaScript代码通常有三种方式:内联(Inline)、内部(Internal)、外部(External)。 Inline(内联) 内联是将JavaScript代码直接写在HTML元素的属性中。由于代码与HTML元素混合在一起,这种方式不易维护和阅读,推荐在特定环境下使用。 以下是内联的示例: <button onclick=&quo…

    JavaScript 2023年5月18日
    00
  • JS动态创建元素的两种方法

    我来为您详细讲解“JS动态创建元素的两种方法”的完整攻略。 1. 使用createElement方法创建元素 使用document.createElement(tagName)方法可以通过JS动态创建一个新的元素节点。其中,tagName参数表示要创建的元素的标签名。 示例一:创建一个<p>元素并添加到页面中 // 创建一个 <p> …

    JavaScript 2023年6月10日
    00
  • js中时间格式化的几种方法

    讲解js中时间格式化的几种方法的攻略如下: 一、JavaScript中的时间表示 在JavaScript中,时间是用毫秒数来表示的。毫秒数是从1970年1月1日00:00:00 UTC开始计算的,也被称为1970年纪元。这个时间点被称为UNIX时间。UNIX时间是一个标准时间,所有的计算机系统都使用它来存储时间数据。 二、格式化时间的方法 在JavaScri…

    JavaScript 2023年5月27日
    00
  • js实现简单模态框实例

    这里是基于 Markdown 编写的攻略,以下将详细讲述如何使用 JavaScript 实现简单模态框。 简述 模态框(Modal)是一种弹出框的交互方式,即在页面的中心或者某个指定区域以弹窗的形式展示内容,遮罩层和窗口通常会阻止用户进行其他操作,只有完成当前操作或者关闭模态框后才能继续页面内的其他操作。 使用步骤 参考以下的实现步骤: 1.创建基本结构 我…

    JavaScript 2023年6月10日
    00
  • JavaScript DOM节点添加示例

    当我们需要对网页中的元素进行动态的增删改时,JavaScript就是我们的好帮手之一。在JavaScript中,通过操作网页文档的对象模型(DOM)来实现对页面元素的增删改查。其中节点的添加,是常用的一种操作。 添加DOM节点的方法 在JavaScript中,有多种方式可以添加DOM节点,以下是其中的两种: 1. createElement()方法 crea…

    JavaScript 2023年6月10日
    00
  • C#应用ToolStrip控件使用方法

    C#应用ToolStrip控件使用方法 在C#中,ToolStrip控件可以用于创建菜单栏、工具栏、状态栏等用户界面元素。本文将介绍在C#应用中如何使用ToolStrip控件。 步骤一:添加ToolStrip控件到窗体 要使用ToolStrip控件,首先需要将其添加到窗体中。可以通过拖拽控件添加的方式,或者在窗体的Load事件中手动创建并添加控件,这里我们以…

    JavaScript 2023年5月28日
    00
  • JS封装cavans多种滤镜组件

    JS封装Cavans多种滤镜组件攻略 在本攻略中,我们将讲解如何通过JavaScript来实现对Cavans多种滤镜的封装。主要囊括了以下内容: 需求分析 功能实现 示例代码 需求分析 我们需要实现一个Cavans滤镜的组件,具有以下功能: 支持黑白滤镜效果 支持模糊滤镜效果 支持浮雕滤镜效果 支持自定义滤镜效果 功能实现 1. 创建Canvas对象 var…

    JavaScript 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部