如何使用异步任务来装饰Siesta请求

时间:2018-06-25 17:46:01

标签: swift siesta-swift

在请求发生之前更改Request执行异步任务的正确方法是什么?

因此,任何请求Rn都需要透明地变为Tn,然后变成Rn。

此处有一些背景知识:该任务是一个第三方SDK,可分发我需要用作原始请求标头的令牌。

我的想法是装饰Rn,但是要做到这一点,我需要将Tn任务转换为Siesta Request,然后才能进行链接。

因此,我包装了异步任务并将其链接到我的原始请求。 因此,任何Rn都将变成Tn.chained { .passTo(Rn) } 这样,这种新行为对于整个应用程序是完全透明的。

问题

这样做,我的代码最终会在Siesta内部先决条件中崩溃: precondition(completedValue == nil, "notifyOfCompletion() already called")

在我的自定义AsyncTaskRequest中,我收集成功,失败,进度等方面的回调,以便在SDK交付令牌时在主队列上触发它们。

我注意到,一旦执行所有删除的回调,崩溃就会消失,但是老实说,我没有找到原因。

我希望有足够的信息来提供一些提示或建议。 预先谢谢你。

1 个答案:

答案 0 :(得分: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

由于这是一个尚未发布的全新功能,非常感谢您提供有关该功能的工作原理以及遇到的任何麻烦的报告。