基于Promise.allSettled的综合案例

194 阅读2分钟

实现效果

image.png

1.分析

  1. 请求 接口 获取-一级商品分类 获取一级分类id
  2. 遍历一级分类id,使用http 生成一组请求Promise,去请求 接口二级分类数据
  3. 使用Promise.allSettled来一次性发送第二步生成的Promise数组得到所有数据
  4. 渲染到页面

基础模板

interface CategoryData {
  id: string
  name: string
  picture: string
  children?: CategoryData[]
}

@Entry
@Component
struct mainContent {
  @State topCategoryList: CategoryData[] = [
    {
      "id": "1005000",
      "name": "居家",
      "picture": "http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-05-06/201516e3-25d0-48f5-bcee-7f0cafb14176.png",
      "children": [
        {
          "id": "1005009",
          "name": "茶咖酒具",
          "picture": "https://yanxuan.nosdn.127.net/3102b963e7a3c74b9d2ae90e4380da65.png?quality=95&imageView"
        },
        {
          "id": "1007000",
          "name": "水具杯壶",
          "picture": "https://yanxuan.nosdn.127.net/45b50d5f8afbd6fdef97314647dcb7db.png?quality=95&imageView"
        },
        {
          "id": "1017000",
          "name": "宠物食品",
          "picture": "https://yanxuan.nosdn.127.net/b42a85ef15f856081ea9f49e5f6893e2.png?quality=95&imageView"
        },
        {
          "id": "109248004",
          "name": "宠物用品",
          "picture": "https://yanxuan.nosdn.127.net/e766b09029ca00680d1e651b5cdc42bd.png?quality=95&imageView"
        }
      ]
    }
  ]

  build() {
    List() {
      ForEach(this.topCategoryList, (item: CategoryData) => {
        ListItemGroup({ header: this.groupHeader(item.name, item.picture) }) {
          ForEach(item.children, (it: CategoryData) => {
            ListItem() {
              Column() {
                Image(it.picture)// .width('80%')
                  .height(90)
                Text(it.name)
                  .fontSize(15)
              }
              .width('100%')
              .alignItems(HorizontalAlign.Center)
            }

          })
        }
      })
    }
    .backgroundColor(Color.White)
    .lanes(4)
    .divider({ strokeWidth: 10, color: '#f6f6f6' })
    .scrollBar(BarState.Off)
  }

  @Builder
  groupHeader(title: string, icon: string) {
    Row({ space: 5 }) {
      Text(title)
        .fontWeight(FontWeight.Bold)
      Image(icon)
        .width(20)
    }
    .width('100%')
    .padding(10)
    .backgroundColor(Color.White)
  }
}

具体实现步骤

1.获取一级分类数据:

发起HTTP请求获取一级分类数据。

将响应结果转换为iTop1Data类型对象。

2.提取一级分类ID:

从一级分类数据中提取所有分类的ID,存储在topids数组中。

3.发起多个二级分类数据请求:

遍历topids数组,对每个ID发起新的HTTP请求以获取对应的二级分类数据。

将每个请求的结果存储在一个Promise<http.HttpResponse>类型的数组plist中。

4.等待所有请求完成:

使用Promise.allSettled等待所有二级分类数据请求完成。

处理每个请求的结果:

如果请求成功,则解析响应结果为iTop2Data类型对象。

将解析后的二级分类数据追加到this.topCategoryList数组中。

如果请求失败,则忽略该结果,将其视为空字符串。

核心代码

/**
 * 异步获取顶级分类列表
 * 此函数通过异步请求获取一级分类数据,并根据一级分类id获取对应的二级分类数据
 */
async getTopCategoryList() {
  // 请求一级分类数据
  const top1 = await req.request(`https://hmajax.itheima.net/api/category/top`)  
  // 将请求结果转换为对象
  let obj: iTop1Data = JSON.parse(top1.result.toString())  
  // 获取一级分类id
  let topids: string[] = obj.data.map(item => {  
    return item.id
  })
  // 创建一个promise数组
  let plist: Promise<http.HttpResponse>[] = [] 
  // 遍历topids,发起二级分类数据请求
  topids.forEach(id => {  
    let reqParam = req.request(`https://hmajax.itheima.net/api/category/sub?id=${id}`)
    plist.push(reqParam) // 将请求结果push到plist中
  })
  // 等待所有请求完成
  Promise.allSettled(plist)
    .then(res => {
      // 遍历plist,处理请求结果
      let top2list = res.map(pres => {  
        if (pres.status == 'fulfilled') { // 判断请求是否成功
          return pres.value.result
        } else {
          return ''
        }
      })
      // 将请求结果转换为对象,并将数据添加到topCategoryList中
      top2list.map(item => {
        let obj: iTop2Data = JSON.parse(item.toString()) 
        this.topCategoryList.push(obj.data) 
      })
    })
}

完整代码

import { http } from '@kit.NetworkKit'

const req = http.createHttp()

export interface iTop1Data {
  data: CategoryData[];
  message: string
}

export interface iTop2Data {
  data: CategoryData;
  message: string
}

interface CategoryData {
  id: string
  name: string
  picture: string
  children?: CategoryData[]
}

@Entry
@Component
struct mainContent {
  @State topCategoryList: CategoryData[] = []

  aboutToAppear(): void {
    this.getTopCategoryList()
  }

  async getTopCategoryList() {
    const top1 = await req.request(`https://hmajax.itheima.net/api/category/top`) // 请求一级分类数据
    let obj: iTop1Data = JSON.parse(top1.result.toString()) // 将请求结果转换为对象
    let topids: string[] = obj.data.map(item => { // 获取一级分类id
      return item.id
    })
    let plist: Promise<http.HttpResponse>[] = [] // 创建一个promise数组
    topids.forEach(id => { // 遍历topids
      let reqParam = req.request(`https://hmajax.itheima.net/api/category/sub?id=${id}`)
      plist.push(reqParam) // 将请求结果push到plist中
    })
    Promise.allSettled(plist)// 等待所有请求完成
      .then(res => {
        let top2list = res.map(pres => { // 遍历plist
          if (pres.status == 'fulfilled') { // 判断请求是否成功
            return pres.value.result
          } else {
            return ''
          }
        })
        top2list.map(item => {
          let obj: iTop2Data = JSON.parse(item.toString()) // 将请求结果转换为对象
          this.topCategoryList.push(obj.data) // 将请求结果添加到topCategoryList中
        })
      })
  }

  build() {
    List() {
      ForEach(this.topCategoryList, (item: CategoryData) => {
        ListItemGroup({ header: this.groupHeader(item.name, item.picture) }) {
          ForEach(item.children, (it: CategoryData) => {
            ListItem() {
              Column() {
                Image(it.picture)// .width('80%')
                  .height(90)
                Text(it.name)
                  .fontSize(15)
              }
              .width('100%')
              .alignItems(HorizontalAlign.Center)
            }

          })
        }
      })
    }
    .backgroundColor(Color.White)
    .lanes(4)
    .divider({ strokeWidth: 10, color: '#f6f6f6' })
    .scrollBar(BarState.Off)
  }

  @Builder
  groupHeader(title: string, icon: string) {
    Row({ space: 5 }) {
      Text(title)
        .fontWeight(FontWeight.Bold)
      Image(icon)
        .width(20)
    }
    .width('100%')
    .padding(10)
    .backgroundColor(Color.White)
  }
}