Is it possible to set a condition on the next queue of DispatchQueue? Supposed there are 2 API calls that should be executed synchronously, callAPI1
-> callAPI2
. But, callAPI2
should be only executed if callAPI1
returning true. Please check code below for more clear situation:
let dispatchQueue: DispatchQueue = DispatchQueue(label: "queue")
let dispatchGroup = DispatchGroup()
var isSuccess: Bool = false
dispatchGroup.enter()
dispatchQueue.sync {
self.callAPI1(completion: { (result) in
isSuccess = result
dispatchGroup.leave()
}
}
dispatchGroup.enter()
dispatchQueue.sync {
if isSuccess { //--> This one always get false
self.callAPI2(completion: { (result) in
isSuccess = result
dispatchGroup.leave()
})
} else {
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: DispatchQueue.main, execute: {
completion(isSuccess) //--> This one always get false
})
Currently above code always returning isSuccess
as false despite on callAPI1
's call returning true, which cause only callAPI1
's is called.
答案 0 :(得分:1)
所有非游乐场代码直接输入答案,预计会出现少量错误。
您似乎正在尝试将异步调用转换为同步调用,而您尝试此操作的方式根本不起作用。假设callAPI1
是异步的,则在:
self.callAPI1(completion: { (result) in
isSuccess = result
}
完成块(很可能)尚未运行,您无法立即测试isSuccess
,如:
self.callAPI1(completion: { (result) in
isSuccess = result
}
if isSuccess
{
// in all probability this will never be reached
}
将代码包装到同步块中无效:
dispatchQueue.sync
{
self.callAPI1(completion: { (result) in
isSuccess = result
}
// at this point, in all probability, the completion block
// has not yet run, therefore...
}
// at this point it has also not run
同步调度只是在不同的队列上运行其块,等待以完成它;如果该块包含异步代码,就像你的那样,它就不会神奇地同步 - 它正常异步执行,同步调度的块终止,同步调度返回,你的代码继续。同步调度没有实际效果(除了在阻止当前队列的同时在不同队列上运行块)。
如果您需要对多个异步调用进行排序,您可以通过多种方式执行此操作。一种方法是简单地通过完成块链接调用。使用这种方法,您的代码变为:
self.callAPI1(completion: { (result) in
if !result { completion(false) }
else
{
self.callAPI2(completion: { (result) in
completion(result)
}
}
}
使用信号量
如果使用上述模式进行了很长时间的此类调用,则代码可以变得非常嵌套,在这种情况下,您可以使用信号量对调用进行排序,而不是嵌套。使用wait()
,可以使用简单的信号量来阻止(线程)执行,直到使用{{1}向(通过未阻塞的线程)发出信号 }。
注意这里强调阻止,一旦你引入了阻止执行的能力,就必须考虑各种问题:其中包括UI响应 - 阻止UI线程不好;死锁 - 例如,如果发出信号量等待和信号操作的代码在同一个线程上执行,那么在等待之后将没有信号......
这是一个示例Swift Playground脚本,用于演示使用信号量。该模式遵循原始代码,但除了布尔值外还使用信号量。
signal()
或... 强>
避免嵌套的另一种方法是设计函数(或运算符),它们采用两种异步方法并通过实现嵌套模式生成单个方法。然后可以将长嵌套序列简化为更线性的序列。这种方法留作练习。
HTH