Как я могу использовать DispatchSemaphore с закрытием
У меня есть значение, которое выглядит так
lazy var authHeaders: [String: String] = {
if shouldTokenBeRefreshed() {
let semaphore = DispatchSemaphore(value: 0)
refreshTokens {
semaphore.signal()
}
semaphore.wait()
}
return ["Authorization": "Bearer \(module.client.credential.oauthToken)"]
}()
Идея в том, чтобы при запросе моего auth headers
Если мой токен истек, я обновлю его, а затем верну новое значение.
func refreshTokens(completion: @escaping () -> Void) {
guard let token = keychain.get("refresh_token") else { return }
module.renewAccessToken(
withRefreshToken: token,
success: { [weak self] credential, response, parameters in
guard let self = self else { return }
self.storeTokens([
"access_token": credential.oauthToken,
"refresh_token": credential.oauthRefreshToken
])
completion()
},
failure: { error in
print(error.description)
})
}
Как это async
операция, я попытался приостановить поток с помощью Semaphore
так что я могу заставить его продолжаться после запуска блока завершения.
Однако звонок не разрешается, и я не уверен, почему.
2 ответа
Это не то, как вы должны использовать DispatchSemaphore
,
Пожалуйста , не заставляйте асинхронный код быть синхронным.
Вам нужно будет реорганизовать свой код, чтобы лучше справляться с асинхронной природой того, чего вы пытаетесь достичь.
Обработчик завершения - это более простой и эффективный способ. Если по какой-то причине вы пытаетесь избежать этого, взгляните на PromiseKit или что-то другое, вспомогательную библиотеку async.
Альтернативным предложением было бы вместо обновления ваших токенов перед полетом, обновить их на 401 и затем воспроизвести ваш оригинальный, обновленный запрос.
Я не уверен, что вы подразумеваете под
Звонок не разрешается
но в вашем примере есть пара моментов, на которые стоит обратить внимание.
- Убедитесь, что authHeaders не инициализируется в основном потоке, поскольку семафор заблокирует ваш пользовательский интерфейс.
- Единственный способ, которым семафору будет дан сигнал о прекращении ожидания, - это выполнение закрытия завершения. В вашем коде есть различные пути, где закрытие завершения не будет выполнено. В
refreshTokens
провалившись первымguard
или попадание в блок сбоя не приведет к закрытию завершения, поэтому семафор не перестанет ждать.