如何在闭包中使用 DispatchSemaphore

How can I use DispatchSemaphore with a Closure

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

   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 时,如果我的令牌已过期,我将刷新它,然后 return 新值。

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 暂停流程,以便在触发完成块后使其继续。

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

我不太清楚你的意思

The call is not resolving

但是在您的示例中有几点需要注意。

  • 确保 authHeaders 没有在主线程上初始化,因为信号量会阻塞您的 UI。
  • 信号量停止等待的唯一方式是执行完成闭包。您的代码中有多种路径不会执行完成闭包。在 refreshTokens 中,第一个 guard 失败或遇到失败块不会执行完成关闭,因此信号量不会停止等待。

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

不要强制异步代码同步。

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

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

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