Skip to content

Commit 62eeba6

Browse files
committed
Merge branch 'development'
* development: ack emits should allow custom types Report errors in SocketData to users. Resolves #677 Fixes #676 fix method name in docs
2 parents b6d0a15 + 7d8eb6f commit 62eeba6

File tree

3 files changed

+118
-13
lines changed

3 files changed

+118
-13
lines changed

SocketIO-MacTests/SocketSideEffectTest.swift

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,81 @@ class SocketSideEffectTest: XCTestCase {
221221
waitForExpectations(timeout: 0.2)
222222
}
223223

224+
func testConnectTimesOutIfNotConnected() {
225+
let expect = expectation(description: "The client should call the timeout function")
226+
227+
socket.setTestStatus(.notConnected)
228+
229+
socket.connect(timeoutAfter: 1, withHandler: {
230+
expect.fulfill()
231+
})
232+
233+
waitForExpectations(timeout: 2)
234+
}
235+
236+
func testConnectDoesNotTimeOutIfConnected() {
237+
let expect = expectation(description: "The client should not call the timeout function")
238+
239+
socket.setTestStatus(.notConnected)
240+
241+
socket.connect(timeoutAfter: 1, withHandler: {
242+
XCTFail("Should not call timeout handler if status is connected")
243+
})
244+
245+
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) {
246+
// Fake connecting
247+
self.socket.setTestStatus(.connected)
248+
}
249+
250+
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.1) {
251+
expect.fulfill()
252+
}
253+
254+
waitForExpectations(timeout: 2)
255+
}
256+
257+
func testErrorInCustomSocketDataCallsErrorHandler() {
258+
let expect = expectation(description: "The client should call the error handler for emit errors because of " +
259+
"custom data")
260+
261+
socket.on(clientEvent: .error) {data, ack in
262+
guard data.count == 3, data[0] as? String == "myEvent",
263+
data[2] is ThrowingData.ThrowingError else {
264+
XCTFail("Incorrect error call")
265+
266+
return
267+
}
268+
269+
expect.fulfill()
270+
}
271+
272+
socket.emit("myEvent", ThrowingData())
273+
274+
waitForExpectations(timeout: 0.2)
275+
}
276+
277+
func testErrorInCustomSocketDataCallsErrorHandler_ack() {
278+
let expect = expectation(description: "The client should call the error handler for emit errors because of " +
279+
"custom data")
280+
281+
socket.on(clientEvent: .error) {data, ack in
282+
guard data.count == 3, data[0] as? String == "myEvent",
283+
data[2] is ThrowingData.ThrowingError else {
284+
XCTFail("Incorrect error call")
285+
286+
return
287+
}
288+
289+
expect.fulfill()
290+
}
291+
292+
socket.emitWithAck("myEvent", ThrowingData()).timingOut(after: 1, callback: {_ in
293+
XCTFail("Ack callback should not be called")
294+
})
295+
296+
waitForExpectations(timeout: 0.2)
297+
}
298+
224299
let data = "test".data(using: String.Encoding.utf8)!
225300
let data2 = "test2".data(using: String.Encoding.utf8)!
226301
private var socket: SocketIOClient!
@@ -231,3 +306,14 @@ class SocketSideEffectTest: XCTestCase {
231306
socket.setTestable()
232307
}
233308
}
309+
310+
struct ThrowingData : SocketData {
311+
enum ThrowingError : Error {
312+
case error
313+
}
314+
315+
func socketRepresentation() throws -> SocketData {
316+
throw ThrowingError.error
317+
}
318+
319+
}

Source/SocketAckEmitter.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,18 @@ public final class SocketAckEmitter : NSObject {
4848

4949
/// Call to ack receiving this event.
5050
///
51+
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
52+
/// will be emitted. The structure of the error data is `[ackNum, items, theError]`
53+
///
5154
/// - parameter items: A variable number of items to send when acking.
5255
public func with(_ items: SocketData...) {
5356
guard ackNum != -1 else { return }
5457

55-
socket.emitAck(ackNum, with: items)
58+
do {
59+
socket.emitAck(ackNum, with: try items.map({ try $0.socketRepresentation() }))
60+
} catch let err {
61+
socket.handleClientEvent(.error, data: [ackNum, items, err])
62+
}
5663
}
5764

5865
/// Call to ack receiving this event.
@@ -98,7 +105,7 @@ public final class OnAckCallback : NSObject {
98105
/// - parameter callback: The callback called when an ack is received, or when a timeout happens.
99106
/// To check for timeout, use `SocketAckStatus`'s `noAck` case.
100107
public func timingOut(after seconds: Int, callback: @escaping AckCallback) {
101-
guard let socket = self.socket else { return }
108+
guard let socket = self.socket, ackNumber != -1 else { return }
102109

103110
socket.ackHandlers.addAck(ackNumber, callback: callback)
104111
socket._emit(items, ack: ackNumber)

Source/SocketIOClient.swift

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,8 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
184184

185185
guard timeoutAfter != 0 else { return }
186186

187-
let time = DispatchTime.now() + Double(UInt64(timeoutAfter) * NSEC_PER_SEC) / Double(NSEC_PER_SEC)
188-
189-
handleQueue.asyncAfter(deadline: time) {[weak self] in
190-
guard let this = self, this.status != .connected && this.status != .disconnected else { return }
187+
handleQueue.asyncAfter(deadline: DispatchTime.now() + Double(timeoutAfter)) {[weak self] in
188+
guard let this = self, this.status == .connecting || this.status == .notConnected else { return }
191189

192190
this.status = .disconnected
193191
this.engine?.disconnect(reason: "Connect timeout")
@@ -232,13 +230,19 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
232230

233231
/// Send an event to the server, with optional data items.
234232
///
233+
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
234+
/// will be emitted. The structure of the error data is `[eventName, items, theError]`
235+
///
235236
/// - parameter event: The event to send.
236237
/// - parameter items: The items to send with this event. May be left out.
237238
open func emit(_ event: String, _ items: SocketData...) {
238239
do {
239240
emit(event, with: try items.map({ try $0.socketRepresentation() }))
240-
} catch {
241-
fatalError("Error creating socketRepresentation for emit: \(event), \(items)")
241+
} catch let err {
242+
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
243+
type: logType)
244+
245+
handleClientEvent(.error, data: [event, items, err])
242246
}
243247
}
244248

@@ -260,6 +264,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
260264
/// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack.
261265
/// Check that your server's api will ack the event being sent.
262266
///
267+
/// If an error occurs trying to transform `items` into their socket representation, a `SocketClientEvent.error`
268+
/// will be emitted. The structure of the error data is `[eventName, items, theError]`
269+
///
263270
/// Example:
264271
///
265272
/// ```swift
@@ -274,8 +281,13 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
274281
open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback {
275282
do {
276283
return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() }))
277-
} catch {
278-
fatalError("Error creating socketRepresentation for emit: \(event), \(items)")
284+
} catch let err {
285+
DefaultSocketLogger.Logger.error("Error creating socketRepresentation for emit: \(event), \(items)",
286+
type: logType)
287+
288+
handleClientEvent(.error, data: [event, items, err])
289+
290+
return OnAckCallback(ackNumber: -1, items: [], socket: self)
279291
}
280292
}
281293

@@ -426,7 +438,7 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
426438

427439
/// Removes handler(s) based on an event name.
428440
///
429-
/// If you wish to remove a specific event, call the `off(if:)` with the UUID received from its `on` call.
441+
/// If you wish to remove a specific event, call the `off(id:)` with the UUID received from its `on` call.
430442
///
431443
/// - parameter event: The event to remove handlers for.
432444
open func off(_ event: String) {
@@ -555,9 +567,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
555567
}
556568

557569
private func _tryReconnect() {
558-
guard reconnecting else { return }
570+
guard reconnects && reconnecting && status != .disconnected else { return }
559571

560-
if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts || !reconnects {
572+
if reconnectAttempts != -1 && currentReconnectAttempt + 1 > reconnectAttempts {
561573
return didDisconnect(reason: "Reconnect Failed")
562574
}
563575

0 commit comments

Comments
 (0)