【问题标题】:In Combine, how do I run a series of futures in sequence?在 Combine 中,我如何按顺序运行一系列期货?
【发布时间】:2020-03-07 22:09:40
【问题描述】:

是否有一个 Combine 运算符可以按顺序运行一系列期货,在开始下一个之前运行每个期货?

我可以用非常凌乱的方式做到这一点:

f1
.flatMap { _ in 
  f2
}.flatMap { _ in 
  f3
}.flatMap { _ in 
  // ... 
}

但我更喜欢这样的:

sequence(f1, f2, f3, ...)

在某些框架中,这看起来像:

f1.then { f2 }.then { f3 }

【问题讨论】:

  • 它解释了“then”的含义。如果您不想将值从一个未来提供给下一个,并且类型可比较,则可以使用append。否则是的,flatMapswitchToLatest 是如何序列化的。我不明白为什么这是个问题。
  • @matt 我查看了append,但它向发布者添加了新元素,而不是附加新发布者。 switchToLatest 将交织事件,所以我认为 flatMap 是我最好的选择。
  • 它不会向发布者添加“新元素”,它让一个发布者运行,然后在完成后让另一个发布者运行。所以他们确实是完全按顺序发布的。
  • 可能与stackoverflow.com/questions/59743938/… 重复;那里有很多有趣的答案。
  • 这才是真正的append。其他的只是方便。

标签: ios macos foundation combine


【解决方案1】:

关键是将 Future 包装在 Deferred 中,这样它就不会执行,直到它的时间:

let f1 = Deferred { Future<Int, Error> { result in

    }
}
let f2 = Deferred { Future<Int, Error> { result in

    }
}
let f3 = Deferred { Future<Int, Error> { result in

    }
}
let jobs = f1
    .append(f2)
    .append(f3)

cancellable = jobs.sink(receiveCompletion: { (completion) in
    print("all three jobs done or one errored.")
}, receiveValue: { value in
    print("value of job:", value)
})

回答 cmets 中的其他问题:

你不能依赖 Deferred 来推迟闭包的执行,直到订阅者进来,因为 Deferred 是一个结构体,每次有新订阅者时都会创建一个新的 Future。

这正是延迟的意义所在。每次有新订阅者时创建一个新的未来,而不是在那之前。另一种选择是在追加中创建期货。

let jobs = Future<Int, Error> { result in }
    .append(Future<Int, Error> { result in })
    .append(Future<Int, Error> { result in })

但是所有三个期货将同时执行它们的代码。我假设你不想要这个。

【讨论】:

  • 谢谢!我正在考虑这一点,但我在“Combine: Asynchronous Programming with Swift”一书中看到了以下注释:“你不能依赖 Deferred 来推迟闭包执行,直到订阅者进来,因为 Deferred 是一个结构,会导致一个新的 Future每次有新订阅者时创建”
  • 这里的事件顺序是.append,而不是Deferred。换句话说,如果你要使用.append,你不需要需要使用Deferred。我们已经在问题本身的 cmets 和链接中提出了链式 .append
  • @matt 我认为@daniel-t 试图适应Futures 立即开始运行的事实,而不是像其他发布者那样等待订阅者。只需附加一堆 Futures 就会同时启动它们,而不是一个接一个地运行它们。
  • 我扩展了答案以涵盖 cmets 中的额外问题。
  • @matt 是的,仅仅创建一个 Future 就会导致它的闭包被调用。如果您不希望在其他发布者完成之前运行未来的关闭,则必须使用 Deferred。问题是关于如何将 Future 的执行推迟到其他 Future 完成执行之后。使用 Deferred 来停止执行直接解决了这个问题。
猜你喜欢
  • 2019-11-04
  • 1970-01-01
  • 2020-07-30
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
相关资源
最近更新 更多