gpt4 book ai didi

swift - 如何保证一起 'start'的两个异步任务在运行另一个之前完成?

转载 作者:可可西里 更新时间:2023-11-01 00:56:54 26 4
gpt4 key购买 nike

我正在设置一个应用程序,它利用 promiseKit 作为订购异步任务的方式。我目前有一个设置可确保按顺序完成两个异步函数(称为 promises)(让我们称它们为 1 和 2),并确保另一组函数(3 和 4)在命令。大致:

import PromiseKit
override func viewDidAppear(_ animated: Bool) {


firstly{
self.promiseOne() //promise #1 happening first (in relation to # 1 and #2)
}.then{_ -> Promise<[String]> in
self.promiseTwo()//promise #2 starting after 1 has completed
}
.catch{ error in
print(error)
}
firstly{
self.promiseThree()//Promise #3 happening first (in relation to #3 and #4)
}.then{_ -> Promise<[String]> in
self.promiseFour()//Promise #4 starting after #3 has completed
}.
.catch{ error in
print(error)
}
}

每个 firSTLy 通过确保第一个函数在第二个函数启动之前完成来确保其中函数的顺序。使用两个单独的 first 确保 1 在 2 之前完成,3 在 4 之前完成,(重要的是)1 和 3 大致同时开始(在viewDidAppear() 的开始)。这是有意为之的,因为 1 和 3 彼此不相关,可以同时启动而不会出现任何问题(2 和 4 也是如此)。问题是有第五个 promise ,我们称之为 promiseFive,它必须 2 和 4 完成后运行。我可以先链接一个确保顺序为 1、2、3、4、5 的 ,但由于 1/2 和 3/4 的顺序不相关,因此以这种方式链接它们会浪费时间。我不确定如何设置它,以便 promiseFive 仅在 2 和 4 都完成后运行。我曾想过在 2 和 4 的末尾调用 bool 检查函数,使得确保其他 firSTLy 已完成然后调用 promiseFive 但是,由于它们开始 异步(1/2 和 3/4),因此有可能使用这种方法,promiseFive 将同时被两者调用,这显然会产生问题。解决此问题的最佳方法是什么?

最佳答案

您可以使用 whenjoin在其他多项 promise 完成后开始做某事。不同之处在于他们如何处理失败的 promise 。听起来你想加入。这是一个具体但简单的示例。

第一个代码块是一个示例,说明如何创建 2 个 promise 链,然后在开始下一个任务之前等待它们都完成。实际完成的工作被抽象成一些功能。专注于此代码块,因为它包含您需要的所有概念信息。

片段

let chain1 = firstly(execute: { () -> (Promise<String>, Promise<String>) in
let secondPieceOfInformation = "otherInfo" // This static data is for demonstration only

// Pass 2 promises, now the next `then` block will be called when both are fulfilled
// Promise initialized with values are already fulfilled, so the effect is identical
// to just returning the single promise, you can do a tuple of up to 5 promises/values
return (fetchUserData(), Promise(value: secondPieceOfInformation))

}).then { (result: String, secondResult: String) -> Promise<String> in
self.fetchUpdatedUserImage()
}

let chain2 = firstly {
fetchNewsFeed() //This promise returns an array

}.then { (result: [String : Any]) -> Promise<String> in

for (key, value) in result {
print("\(key) \(value)")
}
// now `result` is a collection
return self.fetchFeedItemHeroImages()
}

join(chain1, chain2).always {
// You can use `always` if you don't care about the earlier values

let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(self.methodStart)
print(String(format: "All promises finished %.2f seconds later", executionTime))
}

PromiseKit 使用 closures提供它的API。闭包有一个作用域,就像一个 if 语句。如果您在 if 语句的范围内定义一个值,那么您将无法在该范围之外访问它。

您有多种选择可以将多条数据传递到下一个 then block 。

  1. 使用与所有 promise 共享范围的变量(您可能希望避免这种情况,因为它在管理异步数据传播流时对您不利)
  2. 使用自定义数据类型来保存两个(或更多)值。这可以是元组、结构、类或枚举。
  3. 使用集合(如字典),例子在chain2
  4. 返回一个 promise 元组,示例包含在 chain1

在选择方法时,您需要做出最佳判断。

完整代码

import UIKit
import PromiseKit

class ViewController: UIViewController {

let methodStart = Date()

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

<<Insert The Other Code Snippet Here To Complete The Code>>

// I'll also mention that `join` is being deprecated in PromiseKit
// It provides `when(resolved:)`, which acts just like `join` and
// `when(fulfilled:)` which fails as soon as any of the promises fail
when(resolved: chain1, chain2).then { (results) -> Promise<String> in
for case .fulfilled(let value) in results {
// These promises succeeded, and the values will be what is return from
// the last promises in chain1 and chain2
print("Promise value is: \(value)")
}

for case .rejected(let error) in results {
// These promises failed
print("Promise value is: \(error)")
}

return Promise(value: "finished")
}.catch { error in
// With the caveat that `when` never rejects
}
}

func fetchUserData() -> Promise<String> {
let promise = Promise<String> { (fulfill, reject) in

// These dispatch queue delays are standins for your long-running asynchronous tasks
// They might be network calls, or batch file processing, etc
// So, they're just here to provide a concise, illustrative, working example
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(self.methodStart)

print(String(format: "promise1 %.2f seconds later", executionTime))
fulfill("promise1")
}
}

return promise
}

func fetchUpdatedUserImage() -> Promise<String> {
let promise = Promise<String> { (fulfill, reject) in
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(self.methodStart)

print(String(format: "promise2 %.2f seconds later", executionTime))
fulfill("promise2")
}
}

return promise
}

func fetchNewsFeed() -> Promise<[String : Any]> {
let promise = Promise<[String : Any]> { (fulfill, reject) in
DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) {
let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(self.methodStart)

print(String(format: "promise3 %.2f seconds later", executionTime))
fulfill(["key1" : Date(),
"array" : ["my", "array"]])
}
}

return promise
}

func fetchFeedItemHeroImages() -> Promise<String> {
let promise = Promise<String> { (fulfill, reject) in
DispatchQueue.global().asyncAfter(deadline: .now() + 2.0) {
let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(self.methodStart)

print(String(format: "promise4 %.2f seconds later", executionTime))
fulfill("promise4")
}
}

return promise
}
}

输出

promise3 1.05 seconds later
array ["my", "array"]
key1 2017-07-18 13:52:06 +0000
promise1 2.04 seconds later
promise4 3.22 seconds later
promise2 4.04 seconds later
All promises finished 4.04 seconds later
Promise value is: promise2
Promise value is: promise4

关于swift - 如何保证一起 'start'的两个异步任务在运行另一个之前完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45155096/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com