在我的模型中,具有获取数据的功能,该数据需要完成处理程序作为参数:
func fetchMostRecent(completion: (sortedSections: [TableItem]) -> ()) {
self.addressBook.loadContacts({
(contacts: [APContact]?, error: NSError?) in
// 1
if let unwrappedContacts = contacts {
for contact in unwrappedContacts {
// handle constacts
...
self.mostRecent.append(...)
}
}
// 2
completion(sortedSections: self.mostRecent)
})
}
它正在调用另一个函数,该函数执行联系人的异步加载,我将完成情况转发到该函数
fetchMostRecent
具有完成的调用如下所示:
model.fetchMostRecent({(sortedSections: [TableItem]) in
dispatch_async(dispatch_get_main_queue()) {
// update some UI
self.state = State.Loaded(sortedSections)
self.tableView.reloadData()
}
})
有时这是可行的,但是执行的顺序常常不是我期望的那样。问题是,有时completion()
下// 2
的范围之前执行if
下// 1
结束了。
这是为什么?如何确保// 2
在之后开始执行// 1
?
一些观察:
它总是执行2之前1处的值。获得描述的行为的唯一方法是,如果要在for循环内执行其他操作,而该操作本身就是异步的。如果是这种情况,您将使用一个调度组来解决该问题(或重构代码以处理异步模式)。但是,如果看不到for循环中的内容,则很难进一步评论。仅问题中的代码不应显示您所描述的问题。一定是别的东西。
无关的,您应该注意,在异步执行的for循环中更新模型对象(假设它正在后台线程上运行)是有点危险的。更新局部变量,然后通过完成处理程序将其传递回去,让调用者负责将模型更新和UI更新都分派到主队列,这要安全得多。
在注释中,您提到在for
循环中您正在执行异步操作,并且必须在调用completionHandler之前完成某些操作。因此,您将使用调度组来确保仅在完成所有异步任务之后才发生这种情况。
请注意,由于您在for
循环内执行异步操作,因此不仅需要使用调度组来触发这些异步任务的完成,而且可能还需要创建自己的同步队列(您不应该进行突变来自多个线程的数组)。因此,您可以为此创建一个队列。
综合所有这些,您最终会得到以下结果:
func fetchMostRecent(completionHandler: ([TableItem]?) -> ()) {
addressBook.loadContacts { contacts, error in
var sections = [TableItem]()
let group = dispatch_group_create()
let syncQueue = dispatch_queue_create("com.domain.app.sections", nil)
if let unwrappedContacts = contacts {
for contact in unwrappedContacts {
dispatch_group_enter(group)
self.someAsynchronousMethod {
// handle contacts
dispatch_async(syncQueue) {
let something = ...
sections.append(something)
dispatch_group_leave(group)
}
}
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
self.mostRecent = sections
completionHandler(sections)
}
} else {
completionHandler(nil)
}
}
}
和
model.fetchMostRecent { sortedSections in
guard let sortedSections = sortedSections else {
// handle failure however appropriate for your app
return
}
// update some UI
self.state = State.Loaded(sortedSections)
self.tableView.reloadData()
}
或者,在Swift 3中:
func fetchMostRecent(completionHandler: @escaping ([TableItem]?) -> ()) {
addressBook.loadContacts { contacts, error in
var sections = [TableItem]()
let group = DispatchGroup()
let syncQueue = DispatchQueue(label: "com.domain.app.sections")
if let unwrappedContacts = contacts {
for contact in unwrappedContacts {
group.enter()
self.someAsynchronousMethod {
// handle contacts
syncQueue.async {
let something = ...
sections.append(something)
group.leave()
}
}
}
group.notify(queue: .main) {
self.mostRecent = sections
completionHandler(sections)
}
} else {
completionHandler(nil)
}
}
}
异步注解@Async,默认情况下是不生效的,需要的话可以启用. 该加载器有一个可选参数,线程池大小,默认是32,详情可以查阅org.nutz.aop.interceptor.async.AsyncAopIocLoader @IocBy( args={"*json","ioc/", "*anno","net.wendal.nutzbook", "*a
Node 库以多种方式处理异步功能。最常见的模式是 error-first callbacks,但是你还可能会遇到 streams、promises、event emitters、child processes, 或 observables。gulp 任务(task)规范化了所有这些类型的异步功能。 任务(task)完成通知 当从任务(task)中返回 stream、promise、event e
问题内容: 我整天都在整理此问题,希望有人能帮助您确定我的问题。我已经使用Ajax在我的应用程序中创建了“异步进度回调”类型的功能。当我将功能剥离到测试应用程序中时,我得到了预期的结果。见下图: 所需功能 当我使用相同的代码将功能绑定到我的单页应用程序中时,出现了一种阻塞问题,其中所有请求仅在最后一个任务完成后才得到响应。在测试应用程序中,所有请求均会依次响应。服务器报告所有请求的状态(“待定”)
本文向大家介绍Javascript异步执行不按顺序解决方案,包括了Javascript异步执行不按顺序解决方案的使用技巧和注意事项,需要的朋友参考一下 案例分析: 比如执行懒加载时候,onscroll 事件触发多次事件时候会调用多次 ajax 回调事件,由于每个事件返回先后次序并不能保证和触发前一致,所以在数据响应返回后所添加的数据顺序就很在 push 到数组上顺序不一致。 例子1: 这里的并发“
问题内容: 我目前在关闭应用程序的CTRL-C期间关闭异步协程时遇到问题。下面的代码是我现在所拥有的简化版本: 如果按CTRL-C,会给我以下输出: 我对asyncio的经验不是很丰富,所以我很确定我在这里缺少重要的东西。真正让我头疼的是输出之后的部分。从开始,我必须承认我不知道发生了什么。我查看了其他问题,但无法正常工作。那么,为什么这段代码输出类似的东西?如何干净地关闭协程呢? 谢谢你的帮助!
我正在使用Spring任务执行框架执行一个任务。为此,我用@Async注释注释了我的方法,并将以下内容添加到基于XML的应用程序上下文中: 在本例中,我们想知道这个执行器的shutdown方法是如何被调用的?我想确保我的应用不会永远等待这个线程池。 我可以(而不是使用任务名称空间)将我的执行器定义为bean,然后将其destroy方法设置为“shutdown”,但不知道任务名称空间定义样式。 有什