I can not find a solution to my problem: It is necessary to wait for the answer from the closure in the function, tell me how to do it? Here is the code:

import Foundation import RMQClient import SwiftyJSON func getMessage() -> [String:Any] { var answer: [String:Any] = [:] let conn = RMQConnection(uri: "amqp://\(self.login):\(self.password)@\(self.ip1):\(self.port1)", delegate: RMQConnectionDelegateLogger()) conn.start() let ch = conn.createChannel() let q = ch.queue("client_" + String(self.phoneNumber), options: .autoDelete) ch.queueBind("client_" + String(self.phoneNumber), exchange: "sysPay", routingKey: String(self.phoneNumber)) q.subscribe({(_ message: RMQMessage) -> Void in print("Received \(String(data: message.body, encoding: .utf8))") let json = try? JSON(message.body) answer["type"] = message.messageType() for (key, value) in (json?.dictionary)! { answer[key] = value } if answer.count <= 0 { answer["type"] = "no_connect" } }) return answer } 

return always works before receiving a response from the circuit! And here q.subscribe({(_ message: RMQMessage) -> Void result can only be void.

Tell me how to wait for the result from the closure and then return the result from the function? Thank.

    2 answers 2

    The result of the execution comes to q.subscribe later, because the request is executed asynchronously. In this case, it is best to return the answer also asynchronously:

     func getMessage(_ callback: @escaping ([String: Any]) -> Void) { // callback - это функция, которую надо вызвать при получении ответа ... q.subscribe {(_ message: RMQMessage) -> Void in // Подписываемся на результат .... DispatchQueue.main.async { // На всякий случай переводим выполнение в главный поток callback(answer) // Возвращаем результат } } } 

    It is also necessary to change the method call code. If you previously had:

     let messageData = getMessage() // Вызываем фукнкцию и получаем результат print(messageData) // Выводим результат на экран 

    Then with the asynchronous version it looks like this:

     getMessage { messageData in // Вызываем фукнкцию и получаем результат print(messageData) // Выводим результат на экран } 
    • And can I somehow add a timeout here? those. after 10 seconds, if there is no result from the closure then exit the function? - Petrov Kirill
    • And when you call: getMessage {messageData in // Call the function and get the result print (messageData) print ("111") // Display the result on the screen} print ("222") will be displayed first "222" and then "111" ? And all the processing of the result needs to be done in the closure, I understand correctly? - Petrov Kirill
    • Yes, you understood correctly, all the processing of the result should be done in the closure, it is called when a response is received. - Denis
    • You can also make a timeout using the Dispatch.asyncAfter(.now() + 10) { ... } function. Inside it is worth noting that you do not need to call a callback when getting a result and call a callback with nil . This is an example. Perhaps your library has a better way to stop the query. - Denis
    • Alas, the code you cited does not work the second time! - the answer does not come! Everything is good only when you first start! Why is that? - Kirill Petrov

    Made the function global:

     func globalGetMessage2(_ callback: @escaping ( (JSON) -> Void) ) { let timer = Timer.scheduledTimer(withTimeInterval: 9, repeats: false) { _ in callback(JSON()) } print("global getMessage2") let session = Session.instance let conn = RMQConnection(uri: "amqp://\(session.login):\(session.password)@\(session.ip1):\(session.port1)", delegate: RMQConnectionDelegateLogger()) conn.start() let ch = conn.createChannel() let q = ch.queue("client_" + String(session.phoneNum), options: .autoDelete) ch.queueBind("client_" + String(session.phoneNum), exchange: "sysPay", routingKey: String(session.phoneNum)) print("Waiting for messages2.") q.subscribe({(_ message: RMQMessage) -> Void in DispatchQueue.main.async { var json = JSON() print("Received global: \(String(data: message.body, encoding: .utf8))") json = try! JSON(message.body) json["type"].stringValue = message.messageType() conn.close() timer.invalidate() callback(json) } }) } 

    Everything fell into place!

    Here's how with the timeout!

    Thank.

    • You gave the answer, but it contains a question. Nobody can answer you in this thread. Ask a new question and refer to the current one. - 0xdb