【问题标题】:Poll url until response is a certain value轮询 url 直到响应为某个值
【发布时间】:2017-06-17 16:52:07
【问题描述】:

我刚刚开始使用 Swift(一种非常好的语言)进行编码,我正在尝试制作一个要求用户使用第三方登录服务登录的应用。

身份验证流程的基本内容如下所示: 1.用户输入ssn(瑞典人号码)并回车。
2. POST 到返回 json blob 的 url:

{
    "transactionId": "a transaction id",
    "expires": "date sting in some iso format",
    "autostartToken": "irrelevant for my usage"
}

3。轮询使用第 2 步中的 transactionId 的 url。
这个 url 返回一个 json blob:

{
    "state": "OUTSTANDING_TRANSACTION",
    // other stuff that's uninteresting
}

一旦用户使用移动身份验证应用授予访问权限,此 URL 将返回更复杂的 json blob。然后state 将更改为“已完成”。 4. 从可以从步骤 3 中的 blob 获得的最终 url 接收身份验证令牌(一旦状态为“COMPLETED”。
5. ???
6.利润!

所以我的“问题”是我无法真正弄清楚(以我有限的 swift 知识)如何执行第 3 步。轮询 url 直到状态为“COMPLETED”(或第 2 步的过期时间已过,它应该会失败)。

我在 javascript 中做了一个 hacky 尝试来试用该服务,它看起来像这样:

this.postMethodThatReturnsAPromise(url, data).then(response => {
    let {transactionId} = response.body;
        let self = this,
            max = 10,
            num = 0;
        return new Promise(function (resolve, reject) {
            (function poll() {
                self._get(`baseurl/${transactionId}`).then(res => {
                    let {state} = res.body;
                    if (state !== 'COMPLETE' && num < max) {
                        setTimeout(poll, 2000);
                    } else if (state === 'COMPLETE') {
                        return resolve(res);
                    }
                });
                num++;
            })();
        });
    })

我如何在 swift 3 中使用 Alamofire 和 Promisekit 做到这一点?

return Alamofire.request(url, method: .post, /* rest is omitted */).responseJSON().then { response -> String in
    let d = res as! Dictionary<String, Any>
    return d["transactionId"]
}.then { transactionId -> [String: Any] in
    // TODO: The polling until blob contains "state" with value "COMPLETED"
    // Return the final json blob as dict to the next promise handler
}.then { data in
}

【问题讨论】:

    标签: swift promise alamofire promisekit


    【解决方案1】:

    这是这个想法的一个很好的通用版本:

    发件人:https://gist.github.com/dtartaglia/2b19e59beaf480535596

    /**
    Repeadetly evaluates a promise producer until a value satisfies the predicate.
    `promiseWhile` produces a promise with the supplied `producer` and then waits
    for it to resolve. If the resolved value satifies the predicate then the
    returned promise will fulfill. Otherwise, it will produce a new promise. The
    method continues to do this until the predicate is satisfied or an error occurs.
    - Returns: A promise that is guaranteed to fulfill with a value that satisfies
    the predicate, or reject.
    */
    
    func promiseWhile<T>(pred: (T) -> Bool, body: () -> Promise<T>, fail: (() -> Promise<Void>)? = nil) -> Promise<T> {
        return Promise { fulfill, reject in
            func loop() {
                body().then { (t) -> Void in
                    if !pred(t) { fulfill(t) }
                    else {
                        if let fail = fail {
                            fail().then { loop() }
                            .error { reject($0) }
                        }
                        else { loop() }
                    }
                }
                .error { reject($0) }
            }
            loop()
        }
    }
    

    【讨论】:

      【解决方案2】:

      这是我想出的,似乎工作正常。

      }.then { transactionId -> Promise<PMKDataResponse> in
          var dataDict: Dictionary<String, Any> = ["state": "unknown"]
      
          return Promise { fullfill, reject in
              func poll() {
                  // Method that fires an Alamofire get request and returns a Promise<PMKDataResponse>
                  self._get("baseurl/\(transactionId)").then { response -> Void in
                      // .toDictionary() is a extension to Data that converts a Data into a dictionary.
                      dataDict = response.data.toDictionary()
                      let state: String = dataDict["state"] as! String
                      if (state != "COMPLETE") {
                          after(interval: 2).then {
                              poll()
                          }
                      } else if (state == "COMPLETE") {
                          fullfill(response)
                      }
                  }
              }
              poll()
          }
      }
      

      显然,这不会检查交易的到期日期,但现在没关系。哦,缺乏错误处理......?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-31
        • 1970-01-01
        • 2011-06-09
        • 2021-09-16
        相关资源
        最近更新 更多