es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Función de transformación que combina editores y consumidores en una función asíncrona.

Tengo la siguiente función loadData y quiero usarla dentro de refreshable de una lista SwiftUI. Para esto, necesito convertirla en una función async:

func loadData() async {
  // Publishers
  let followersPublisher = await modelLoader.loadAllFollowers(withId: id)
  let followingPublisher = await modelLoader.loadAllFollowing(withId: id)
  let friendshipsPublisher = await Publishers.Zip(followersPublisher, followingPublisher)
    .share()
    .eraseToAnyPublisher()

  // Sinks
  getFollowers(from: followersPublisher)
  getFollowerChange(
    from: followersPublisher,
    cachedFollowers: followers
  )
  getFollowing(from: followingPublisher)
  getNotFollowingUserBack(from: friendshipsPublisher)
  getUserNotFollowing(from: friendshipsPublisher)

  await followersPublisher
    .connect()
    .store(in: &cancellables)
  await followingPublisher
    .connect()
    .store(in: &cancellables)
}

Dentro de esta función, todas las funciones separadas utilizan los sink de Publisher. Por ejemplo:

private func getFollowing(from publisher: Publishers.MakeConnectable<><><user>, Never>>) {
  publisher
    .sink(
      receiveCompletion: { _ in },
      receiveValue: { [weak self] following in
        self?.following = following
      }
    )
    .store(in: &cancellables)
}

¿Cómo puedo convertirlo en una función async para poder usar await con él?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para convertir la función loadData() en una función async, sigue estos pasos:

    1. Actualiza la firma de la función para incluir async antes del tipo de retorno:
      async func loadData() {
      
    2. Modifica cada una de las funciones get para devolver una “Promise” que se resuelve con el valor esperado:
      private func getFollowing(from publisher: Publishers.MakeConnectable<><><user>, Never>>) -> Promise<><user>> {
        return Promise { resolve in
          publisher
            .sink(
              receiveCompletion: { _ in },
              receiveValue: { following in
                resolve(following)
              }
            )
            .store(in: &cancellables)
        }
      }
      
    3. Utiliza await para llamar a cada una de las funciones get y espera a que se resuelvan antes de continuar:
      async func loadData() {
        // Publishers
        let followersPublisher = modelLoader.loadAllFollowers(withId: id)
        let followingPublisher = modelLoader.loadAllFollowing(withId: id)
        let friendshipsPublisher = Publishers.Zip(followersPublisher, followingPublisher)
          .share()
          .eraseToAnyPublisher()
      
        // Await the promises
        let followers = try await getFollowers(from: followersPublisher)
        let following = try await getFollowing(from: followingPublisher)
        let notFollowingUserBack = try await getNotFollowingUserBack(from: friendshipsPublisher)
        let userNotFollowing = try await getUserNotFollowing(from: friendshipsPublisher)
      
        // Store the results
        self.followers = followers
        self.following = following
        self.notFollowingUserBack = notFollowingUserBack
        self.userNotFollowing = userNotFollowing
      
        followersPublisher
          .connect()
          .store(in: &cancellables)
        followingPublisher
          .connect()
          .store(in: &cancellables)
      }
      

    Al modificar las funciones get para devolver “Promises” y utilizar await para resolverlas dentro de la función loadData(), podemos convertirla en una función async que se puede utilizar con refreshable en una lista de SwiftUI.

Comments are closed.