Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GET/POST asynchronous #52

Closed
karlzakhary opened this issue Dec 4, 2017 · 7 comments
Closed

GET/POST asynchronous #52

karlzakhary opened this issue Dec 4, 2017 · 7 comments

Comments

@karlzakhary
Copy link

I know that mutate is used for updating the state whenever actions happen, I am trying to make an API get request to receive an access token to make after that GET request, a POST request using that token in my authorization header in that post request, how do I make only one get request then the post request using that access token obtained from my first get request?

@devxoul
Copy link
Member

devxoul commented Dec 4, 2017

I think you can use flatMap() for concatMap() to do that.

api.get("/grant-access-token")
  .flatMap { accessToken in
    return api.post("/foo", accessToken: accessToken)
  }

@karlzakhary
Copy link
Author

karlzakhary commented Dec 4, 2017

 func mutate(action: Action) -> Observable<Mutation> {
    let idUsr = Configuration.apiKey
        switch action {
    
        case let .send(text):
      //print(idUsr)
        let welcomeMessage = self.provider.cleverbotService
        .getReply(text: text, authorization:idUsr)
        .map { incomingMessage in Message.incoming(incomingMessage) }
        
        let outgoingMessage = Observable.just(Message.outgoing(.init(text: text)))
        
        let incomingMessage = self.provider.cleverbotService
        .getReply(text: text, authorization:idUsr)
        .map { incomingMessage in Message.incoming(incomingMessage) }
      return Observable.of(outgoingMessage, incomingMessage).merge()
        .map { message in Mutation.addMessage(message) }
            
        
        }
  }

/////////////


 func getReply3() -> Observable<WelcomeMessage> {
        var uuid = ""
        var urlRequest = URLRequest(url: URL(string: "http://thawing-refuge-61104.herokuapp.com/welcome")!)
        urlRequest.httpMethod = HTTPMethod.get.rawValue
        return Observable.create { observer in
        let request = Alamofire.request(urlRequest)
            
            .responseString { response in
                switch response.result {
                case .success(let JSON):
                    
                    do {
                        //print(authorization)
                        let response = try Mapper<WelcomeMessage>().map(JSONString:JSON)
                        //print (response.message)
                        
                        observer.onNext(response)
                        observer.onCompleted()
                    } catch (let error) {
                        observer.onError(error)
                    }
                case .failure(let error):
                    observer.onError(error)
                }
        }
        return Disposables.create {
            request.cancel()
        }
    }
}


/////////////////

    func getReply(text: String, authorization: String) -> Observable<IncomingMessage> {
        
        var urlRequest = URLRequest(url: URL(string: "http://thawing-refuge-61104.herokuapp.com/chat")!)
        urlRequest.httpMethod = HTTPMethod.post.rawValue
        urlRequest = try! URLEncoding.default.encode(urlRequest, with: nil)
        urlRequest.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        let body: [String: Any] = ["message": text]
        
        urlRequest.setValue(authorization,forHTTPHeaderField: "Authorization")
        
        return Observable.create { observer in
            do {
                let jsonData = try JSONSerialization.data(withJSONObject: body, options: .prettyPrinted)
                urlRequest.httpBody = jsonData
                
            }
            catch  (let error){
                print (error) }
            let request = Alamofire.request(urlRequest)
                .responseString{ response in
                    switch response.result {
                    case .success(let JSON):
                        do {
                            //print(authorization)
                            let response = try Mapper<IncomingMessage>().map(JSONString:JSON)
                            //print (response.message)
                            
                            observer.onNext(response)
                            observer.onCompleted()
                        } catch (let error) {
                            observer.onError(error)
                        }
                    case .failure(let error):
                        observer.onError(error)
                    }
            }
            return Disposables.create {
                request.cancel()
            }
        }
    }

The first function is the mutate function, the 2nd one is my post request, the 3rd is the get request. Can you please make it much clearer on how to pass the token that comes from the response to the post request ONLY ONCE ?

@devxoul
Copy link
Member

devxoul commented Dec 5, 2017

What do you mean 'ONLY ONCE'?

@karlzakhary
Copy link
Author

I need to make a get request only once and then inject the synchronous post requests I'm doing with the token that comes from the response of the get request

@karlzakhary
Copy link
Author

I want to make just one GET request, and then several post requests that depend on the response of that GET request when I tap the button send which is in the Cleverbot example.
The difference is that in the Cleverbot example is that when you tap on the SEND button, you make only one request, what I want to do is to make a POST request everytime I tap on the button using the saved token that I obtain only once from the GET request that happened as a pre-requisite to the synchronous POST requests

@devxoul
Copy link
Member

devxoul commented Dec 5, 2017

I think this would work:

enum Mutation {
  case setAccessToken(accessToken)
  case addMessage(Message)
}

struct State {
  var accessToken: String?
}

func mutate(action: Action) -> Observable<Mutation> {
  switch action {
  case .send(text):
    if let accessToken = self.currentState.accessToken {
      return api.getReply(text: text, accessToken: accessToken)
    } else {
      return api.grantAccessToken().flatMap { accessToken -> Observable<Mutation> in
        return Observable.concat([
          Observable.just(Mutation.setAccessToken(accessToken)),
          api.getReply(text: text, accessToken: accessToken).map(Mutation.addMessage),
        ])
      }
    }
  }
}

func reduce(state: State, mutation: Mutation) -> State {
  var newState = state
  switch mutation {
  case let .setAccessToken(accessToken):
    newState.accessToken = accessToken

  case let .addMessage(message):
    newState.foo = bar
  }
  return newState
}

@karlzakhary
Copy link
Author

That helped really much, THANK YOU!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants