我dispatch_group
用来调用Firebase请求函数,并在请求完成后得到通知,以便能够处理结果。在这种情况下,我只是打印了一条语句。
func loadStuff() {
dispatch_group_enter(group)
myFirebaseFunction() {
dispatch_group_leave(group)
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
}
func myFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeEventType(.Value, withBlock: { snapshot in
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
completionHandler()
})
}
这段代码工作正常。 问题
在于,在运行时,数据将被添加到Firebase数据库中。这就是为什么我必须使用observeEventType
而不是observeSingleEventOfType
。
这意味着在运行时会有一个观察者,并且如果数据已添加到数据库中,myFirebaseFunction
则将再次调用其中的块。
一旦发生这种情况,该应用就会崩溃,因为dispatch_group_leave(group)
没有调用dispatch_group_enter(group)
。只要我说对了。
dispatch_group_enter(group)
myFirebaseFunction() {
dispatch_group_leave(group) // crash here
}
如果将其更改为observeSingleEventOfType
,则不会发生崩溃,但是不会观察到新添加到Firebase的数据。
dispatch_group
与多个运行的Web服务一起使用的最佳实践是什么?或者我该怎么做才能解决我的问题?非常感谢您的帮助。
PS当前,我正在使用Swift 2.3,但计划将其升级到Swift 3,因此收到能够同时解决这两个问题的答案将非常棒。
如您所述,呼叫dispatch_group_enter
和dispatch_group_leave
必须保持平衡。在这里,您无法平衡它们,因为仅执行实际实时提取的函数会离开。
如果myFirebaseFunction
始终在该调度组上执行其工作没有问题,则可以将进入和离开都放在其中,也许使用beginHandler和completedHandler:
func loadStuff() {
myFirebaseFunction(beginHandler: {
dispatch_group_enter(group)
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
}, completionHandler: { dispatch_group_leave(group) })
}
func myFirebaseFunction(beginHandler: () -> (), completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeEventType(.Value, withBlock: { snapshot in
beginHandler()
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
completionHandler()
})
}
在这里,完成处理程序仍将设置为dispatch_group_leave
by
loadStuff
,但是还有一个begin处理程序将调用dispatch_group_enter
and
dispatch_group_notify
。需要在开始时调用notify的原因是,我们需要确保在调用notify之前已经进入了该组,否则如果该组为空,则notify块将立即执行。
即使传递给dispatch_group_notify
通知的块在组上执行,即使传递给该块的块也只会被调用一次。因此,observeEventType
在组上进行每次自动呼叫可能是安全的。然后,在这些功能之外需要等待加载完成的任何时间,您都可以调用notify。
编辑: 由于每次beginHandler
调用notify都会被调用,因此此方法实际上会导致每次调用notify块,因此它可能不是理想的选择。
如果您真正需要的仅是第一次调用observeEventType
使用该组,则一个选项是具有的两个版本myFirebaseFunction
:一个与您已经拥有的版本非常相似,另一个与一起使用observeSingleEventOfType
。然后加载的东西可以调用这两个函数,仅dispatch_group_leave
作为完成传递给其中一个:
func loadStuff() {
dispatch_group_enter(group)
myInitialFirebaseFunction() {
dispatch_group_leave(group)
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
myFirebaseFunction({})
}
func myInitialFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
processSnapshot(snapshot)
completionHandler()
})
}
func myFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
processSnapshot(snapshot)
completionHandler()
})
}
func processSnapshot(snapshot: FDataSnapshot) {
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
}
请注意,由于loadStuff
在“方法2”中基本上从Firebase加载了两次,因此效率可能不如您所愿。在这种情况下,您可以改用a
Bool
来确定是否应调用请假:
var shouldLeaveGroupOnProcess = false
func loadStuff() {
dispatch_group_enter(group)
shouldLeaveGroupOnProcess = true
myFirebaseFunction() {
if shouldLeaveGroupOnProcess {
shouldLeaveGroupOnProcess = false
dispatch_group_leave(group)
}
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
}
func myFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeEventType(.Value, withBlock: { snapshot in
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
completionHandler()
})
}
在这里,即使observeEventType
在初始加载期间多次调用,也leave
可以保证仅被调用一次,并且不会发生崩溃。
PS当前,我正在使用Swift 2.3,但计划将其升级到Swift 3,因此收到能够同时解决这两个问题的答案将非常棒。
在Swift 3中Dispatch进行了全面的改进(它是面向对象的),因此在两者上都能很好地工作的代码并不是一件真正的事情:)
但是以上三种方法中每种方法的概念都是相同的。在Swift 3中
DispatchGroup
dispatch_group_enter
现在enter
是组上的实例方法dispatch_group_leave
现在leave
是组上的实例方法dispatch_group_notify
现在notify
是组上的实例方法我是个很新的程序员。我在工作中的任务之一是让我们的定制工具创建草稿电子邮件,并将其放入运行该工具的用户的草稿电子邮件文件夹中。我们目前使用Exchange Server 2010(但正在迁移到Exchange Online)。 这个链接讨论了UseDefaultCredentials,但我似乎不知道如何实现它。我创建了一个名为service的ExchangeService对象,并使用以下凭据与Ex
我在Scala上使用Play 2.5,我创建了一个类,可以多次调用外部web服务。 外部Web服务在某些条件下被调用并得到ok或nok的简单响应。如果可以,那么我应该更新内部对象状态,如果可以,我现在什么也不做。 这是我的类,它将String的列表作为参数,并返回要在控制器中处理的对象的Future列表。 是列表类型的列表,但我希望它只是一个简单的响应列表。 1)如何简化和纠正我的代码以获得响应列
JSON似乎打印到浏览器窗口,所以我不完全确定这种方法有什么问题?请谁能提供一些帮助,为什么这可能不起作用? 谢谢
问题内容: 我对WireMock完全陌生。 到目前为止,我一直在使用通过SOAPUI进行模拟响应。我的用例很简单: 只需将SOAP XML请求发送到不同的端点(http:// localhost:9001 / endpoint1 ),然后返回固定的XML响应。但是MockWrire必须作为独立服务部署到专用服务器上,该服务器将充当从中提供模拟响应的中心位置。 只是想要一些开始的建议。如我所见,Wi
如何编写angular服务方法参数来调用restful webservice Spring MVC,其签名中包含@RequestBody和@RequestParam。 Java代码: 角服务方法: 如果你帮助我,我将不胜感激。祝您愉快!
我一直在努力寻找一些资源来帮助解释我们如何使用Web应用程序服务的文件存储。 可以将其与旧的Web角色一起使用,请参阅此处(在云服务(Web和辅助角色)中使用Azure文件服务)。 但是,“Azure Web服务”中没有OnStart()方法。