轮询网址直到回复为特定值

时间:2017-06-17 16:52:07

标签: swift promise alamofire promisekit

我刚开始用Swift编写代码(一种非常好的语言),我正在尝试创建一个需要用户使用第三方登录服务登录的应用程序。

身份验证流程的基础知识如下所示: 1.用户输入ssn(swedish personnummer)并点击进入。
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返回一个json blob:

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

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

所以我的“问题”是我无法弄清楚(用我有限的快速知识)如何做第3步。轮询网址直到状态为“已完成”(或者步骤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
}

2 个答案:

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

答案 1 :(得分:0)

在这里,我提出的似乎工作正常。

}.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()
    }
}

显然,这不会检查交易的到期日期,但现在还可以。哦,缺乏错误处理...