2017-06-17 19 views
0

私はちょうどSwift(とても素敵な言語)でコーディングを始めました。ユーザーにサードパーティのログインサービスを使用してログインする必要があるアプリを作ろうとしています。返信が特定の値になるまでURLをポップ

認証フローの基本は次のようになります。 1.ユーザーはssn(swedish personnummer)を入力し、enterを押します。
2. JSONブロブを返すURLにPOST:

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

3ポーリング手順2
からこのURLをtransactionIdを使用するURLは、JSONブロブを返す:

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

ユーザーがモバイル認証アプリを使用してアクセス権を付与すると、このURLはより複雑なjsonブロブを返します。 stateは「完了」に変わります。 4.状態が「完了」されると(ステップ3でブロブから得ることができる最後のURLから認証トークンを受信します。
5. ???
6.利益を!だから私の

」ステップ3を行う方法を(私の限られた迅速な知識で)本当に把握することができないということです。状態が「完了」(またはステップ2からの期限が過ぎて失敗する)になるまでURLをポーリングします。

私は、サービスを試してJavaScriptでハックの試みを行っている、それは一種の次のようになります。

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++; 
      })(); 
     }); 
    }) 

AlamofireとPromisekitを使用して迅速に3を行う方法はありますか?

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 
} 

答えて

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

明らかに、これはトランザクションの有効期限をチェックすることはありませんが、それは今は大丈夫です。ああおよびエラー処理の欠如...

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() 
    } 
} 
関連する問題