Home > OS >  Async await list detail
Async await list detail

Time:11-03

I'm trying to fetch a detailed list of items through a multi step async call. First I fetch a list of identifiers, after which I fetch the details for each of these identifiers.

func fetchList() async -> [UUID] {
    // some async network call here
    await Task.sleep(2)
    return [UUID(), UUID(), UUID()]
}

func fetchDetail(forUUID uuid: UUID) async -> String {
    // some async network call here
    await Task.sleep(1)
    return "\(uuid.uuidString.reversed())"
}

Individually these function work fine, but I'm stuck when I want to try and use a .map on the list.

Task {
    let list = await fetchList()
    let details = await list.map { fetchDetail(forUUID: $0) } // Does not work
}

I did find out about the withTaskGroup function and I could of course append to an array of items asynchronously, but I was wondering if there is a better way to achieve this functionality.

CodePudding user response:

I believe you don't need to use 'await' in front of list.map, as the function you are calling already has 'await' in it. Plus, ".map" is synchronous.

CodePudding user response:

Map for async code needs AsyncSequence to work on.

struct DelayedUUIDs: AsyncSequence {
  typealias Element = UUID

  struct DelayedIterator: AsyncIteratorProtocol {
    private var internalIterator = [UUID(), UUID(), UUID()].makeIterator()

    mutating func next() async -> UUID? {
      await Task.sleep(1_000_000_000)
      return internalIterator.next()
    }
  }

  func makeAsyncIterator() -> DelayedIterator {
    DelayedIterator()
  }
}

func fetchList() async -> DelayedUUIDs {
    // some async network call here
    await Task.sleep(1)
    return DelayedUUIDs()
}

func fetchDetail(forUUID uuid: UUID) async -> String {
    // some async network call here
    await Task.sleep(1)
    return "ID: \(uuid.uuidString)"
}


Task {
    let list = await fetchList()
    let details = list.map({ id in await fetchDetail(forUUID: id) })
    for await value in list {
      print(Date())
      print(value)
    }
    for await value in details {
      print(Date())
      print(value as String)
    }
}
  • Related