如何用异步任务装饰午睡请求
Posted
技术标签:
【中文标题】如何用异步任务装饰午睡请求【英文标题】:How to decorate Siesta request with an asynchronous task 【发布时间】:2018-06-25 17:46:00 【问题描述】:在请求发生之前更改 Request
执行异步任务的正确方法是什么?
所以任何请求 Rn 都需要变成透明的 Tn 然后 Rn。
这里有一点背景:任务是一个第三方 SDK,它调度我需要用作原始请求的标头的令牌。
我的想法是装饰 Rn,但在此过程中我需要将我的 Tn 任务转换为 Siesta Request
然后我可以链接。
所以我包装了异步任务并链接到我的原始请求。
因此任何Rn
都会变成Tn.chained .passTo(Rn)
这样,这种新行为对整个应用程序来说是完全透明的。
问题
这样做我的代码最终会在 Siesta 内部前提条件下崩溃:
precondition(completedValue == nil, "notifyOfCompletion() already called")
在我的自定义 AsyncTaskRequest 中,我收集成功、失败、进度等的回调,以便在 SDK 传递令牌时在主队列上触发它们。
我注意到一旦执行删除所有存储的回调,崩溃就消失了,但老实说我没有找到原因。
我希望有足够的信息来提供一些提示或建议。 提前谢谢你。
【问题讨论】:
【参考方案1】:是的,实现 Siesta 的 Request
接口不是野餐。其他人有 exactly the same problem — 幸运的是 Siesta 版本 1.4 includes a solution。
新功能的文档仍然很薄。要使用新的 API,您将实现新的 RequestDelegate
协议,并将您的实现传递给 Resource.prepareRequest(using:)
。这将返回一个您可以在标准 Siesta 请求链中使用的请求。结果将如下所示(警告 - 未经测试的代码):
struct MyTokenHandlerThingy: RequestDelegate
// 3rd party SDK glue goes here
...
service.configure(…)
if let authToken = self.authToken
$0.headers["X-Auth-Token"] = authToken // authToken is an instance var or something
$0.decorateRequests
self.refreshTokenOnAuthFailure(request: $1)
func refreshTokenOnAuthFailure(request: Request) -> Request
return request.chained
guard case .failure(let error) = $0.response, // Did request fail…
error.httpStatusCode == 401 else // …because of expired token?
return .useThisResponse // If not, use the response we got.
return .passTo(
self.refreshAuthToken().chained // If so, first request a new token, then:
if case .failure = $0.response // If token request failed…
return .useThisResponse // …report that error.
else
return .passTo(request.repeated()) // We have a new token! Repeat the original request.
)
func refreshAuthToken() -> Request
return Request.prepareRequest(using: MyTokenHandlerThingy())
.onSuccess
self.authToken = $0.jsonDict["token"] as? String // Store the new token, then…
self.invalidateConfiguration() // …make future requests use it
要了解如何实现RequestDelegate
,目前最好的办法是查看new API docs directly in the code。
由于这是一项尚未发布的全新功能,我非常感谢您报告它的工作原理以及您遇到的任何问题。
【讨论】:
这是个好消息!我没有遇到这个PR。我会尝试探索它。有 1.4 版本的 ETA 吗? 很遗憾,由于 Swift 4.1,我无法在此使用。我的项目很快就会迁移,但不是现在 :( 无论如何,我一直看到 authToken 的失败模式很好,但这不符合我的需要。(R -> Fail -> GetToken -> Success -> Invalidate -> R.Repeated ) 做 GetToken -> Success -> Invalidate -> R.Repeated 有什么陷阱吗?原因是:第 3 个 SDK 建议这种行为。令牌被 SDK 缓存并仅在实际需要时刷新。 是的,您描述的模式应该可以正常工作。请求链 API 的全部意义在于允许您设置任意重试路径,即我们的微型多请求状态机。一个可能的陷阱:要在您获得令牌后强制它重新读取配置,您可能需要执行request.repeated()
,即使您从未启动过原始请求。
哦,根据 1.4 版本:ETA 是我一有时间完成文档并发布内务管理。
1.4 现已推出。以上是关于如何用异步任务装饰午睡请求的主要内容,如果未能解决你的问题,请参考以下文章
Python学习---Python的异步---asyncio模块(no-http)