Skip to content

Commit dd2167a

Browse files
committed
Report errors in SocketData to users. Resolves #677
1 parent 8e25c6c commit dd2167a

File tree

3 files changed

+72
-5
lines changed

3 files changed

+72
-5
lines changed

SocketIO-MacTests/SocketSideEffectTest.swift

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,48 @@ class SocketSideEffectTest: XCTestCase {
254254
waitForExpectations(timeout: 2)
255255
}
256256

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+
257299
let data = "test".data(using: String.Encoding.utf8)!
258300
let data2 = "test2".data(using: String.Encoding.utf8)!
259301
private var socket: SocketIOClient!
@@ -264,3 +306,14 @@ class SocketSideEffectTest: XCTestCase {
264306
socket.setTestable()
265307
}
266308
}
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public final class OnAckCallback : NSObject {
9898
/// - parameter callback: The callback called when an ack is received, or when a timeout happens.
9999
/// To check for timeout, use `SocketAckStatus`'s `noAck` case.
100100
public func timingOut(after seconds: Int, callback: @escaping AckCallback) {
101-
guard let socket = self.socket else { return }
101+
guard let socket = self.socket, ackNumber != -1 else { return }
102102

103103
socket.ackHandlers.addAck(ackNumber, callback: callback)
104104
socket._emit(items, ack: ackNumber)

Source/SocketIOClient.swift

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,19 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
230230

231231
/// Send an event to the server, with optional data items.
232232
///
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+
///
233236
/// - parameter event: The event to send.
234237
/// - parameter items: The items to send with this event. May be left out.
235238
open func emit(_ event: String, _ items: SocketData...) {
236239
do {
237240
emit(event, with: try items.map({ try $0.socketRepresentation() }))
238-
} catch {
239-
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])
240246
}
241247
}
242248

@@ -258,6 +264,9 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
258264
/// **NOTE**: It is up to the server send an ack back, just calling this method does not mean the server will ack.
259265
/// Check that your server's api will ack the event being sent.
260266
///
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+
///
261270
/// Example:
262271
///
263272
/// ```swift
@@ -272,8 +281,13 @@ open class SocketIOClient : NSObject, SocketIOClientSpec, SocketEngineClient, So
272281
open func emitWithAck(_ event: String, _ items: SocketData...) -> OnAckCallback {
273282
do {
274283
return emitWithAck(event, with: try items.map({ try $0.socketRepresentation() }))
275-
} catch {
276-
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)
277291
}
278292
}
279293

0 commit comments

Comments
 (0)