1

我有一个看起来像这样的值

   lazy var authHeaders: [String: String] = {
        if shouldTokenBeRefreshed() {
            let semaphore = DispatchSemaphore(value: 0)
            refreshTokens {
                semaphore.signal()
            }
            semaphore.wait()
        }
        return ["Authorization": "Bearer \(module.client.credential.oauthToken)"]
    }()

这个想法是,在请求 my 时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操作,因此我尝试使用 a 暂停流程,Semaphore以便在触发完成块后使其继续。

但是,电话没有解决,我不确定为什么。

4

2 回答 2

1

我不确定你的意思

通话未解决

但在您的示例中有几件事需要注意。

  • 确保 authHeaders 没有在主线程上初始化,因为信号量会阻塞你的 UI。
  • 信号量停止等待的唯一方法是执行完成闭包。您的代码中有多种路径不会执行完成闭包。在refreshTokens第一个guard失败或命中失败块时不会执行完成闭包,因此信号量不会停止等待。
于 2019-04-26T16:16:35.650 回答
1

这不是您应该使用的方式DispatchSemaphore

不要强制异步代码同步。

您将需要重构代码以更好地处理您尝试实现的异步性质。

完成处理程序是更简单、更有效的方法。如果您出于某种原因试图避免这种情况,请查看 PromiseKit 或其他异步帮助程序库。

另一种建议不是在飞行前更新您的令牌,而是在 401 上更新它们,然后重播您的原始更新请求。

于 2019-04-27T06:04:57.873 回答