ios - 有没有办法快速确保 API 调用在竞争条件下只被调用一次
问题描述
在我的应用程序中,我需要调用一个getGroup()
函数,该函数使用用户信息访问我们的 CMS,并根据 CMS 中当前的信息和内容将它们放在一个组中。此组信息包含在我们其他 API 调用的 URL 中。
问题是,当应用程序启动并且用户的组尚未缓存时,这些 API 调用中的每一个都会触发 getGroup 以实际进行 API 调用,而不仅仅是获取缓存的组。我想减少它,以便只进行一次调用,并且对该函数的其他调用等到听到响应。
我想做的伪代码示例:
var isGettingGroup = false
func getGroup(completion: (group?, error?)) {
if isGettingGroup {
wait for notification
}
if let group = groupFromCache() {
completion(group, nil)
} else {
isGettingGroup = true
callGetGroupAPI() { group, error in
completion(group, error)
cacheGroup(group)
isGettingGroup = false
send notification to continue
}
}
}
我试过使用信号量,但我认为我需要一些更全球化的东西,比如来自NotificationCenter
. 我的主要问题是根据通知暂停单个函数调用,而不是等待分配的时间。我用过DispatchGroups
很多次,但这似乎是相反的问题——多个函数在一个调用上等待,而不是在函数/块上等待多个。
提前致谢
解决方案
该调用只进行一次,对该函数的其他调用等待直到听到响应
该函数应在串行后台队列上同步运行其代码。这使得它不可能被两个不同的线程同时调用。这是您的伪代码的伪代码;未经测试,但它显示了我相信会起作用的东西:
let q = DispatchQueue()
func getGroup(completion: (group?, error?)) {
q.sync { // lock out any other calls to getGroup until we finish
let g = DispatchGroup()
g.enter()
if let group = groupFromCache() {
completion(group, nil)
g.leave()
} else {
callGetGroupAPI() { group, error in
completion(group, error)
cacheGroup(group)
g.leave()
}
}
g.notify()
}
}
我不完全确定需要调度组,但我已将其放入以将所有内容保持在sync
.
编辑OP 说调度组实际上是需要的,你需要说g.wait()
而不是notify()
,但否则这是可行的。
推荐阅读
- html - 在 HTML 中对字符串插值进行样式化 - Angular
- python - smtplib/exchangelib 连接到电子邮件服务器错误
- automata - 逐步过渡 FSM
- java - 如何在Java中将参数与命令分开?
- python - 为什么 keras 中的 model.fit 函数显着增加 RAM 内存?
- reactjs - 如何在 ReactJS 中做动态图像?
- php - laravel 从多个 smtp 电子邮件发送邮件
- scikit-learn - sklearn 的 predict_proba 应该返回直线吗?
- java - 上传到服务器之前的 GWT 图片上传预览图片
- javascript - 如何在特殊字符之前获取子字符串?