@@ -48,6 +48,63 @@ ROS 2 services provide a request-response communication pattern where clients se
4848  -  Asynchronous request handling with callbacks
4949-  ** Run Command** : ` node example/services/client/client-example.js ` 
5050
51+ #### Async Service Client (` client/async-client-example.js ` )  
52+ 
53+ ** Purpose** : Demonstrates modern async/await patterns for service communication, solving callback hell and providing cleaner error handling.
54+ 
55+ -  ** Service Type** : ` example_interfaces/srv/AddTwoInts ` 
56+ -  ** Service Name** : ` add_two_ints ` 
57+ -  ** Functionality** :
58+   -  Multiple examples showing different async patterns
59+   -  Simple async/await calls without callbacks
60+   -  Timeout handling with configurable timeouts
61+   -  Request cancellation using AbortController
62+   -  Sequential and parallel service calls
63+   -  Comprehensive error handling
64+ -  ** Features** :
65+   -  ** Modern JavaScript** : Clean async/await syntax instead of callback hell
66+   -  ** Timeout Support** : Built-in timeout with ` options.timeout `  (uses ` AbortSignal.timeout() `  internally)
67+   -  ** Cancellation** : Request cancellation using ` AbortController `  and ` options.signal ` 
68+   -  ** Error Types** : Specific error types (` TimeoutError ` , ` AbortError ` ) for better error handling (async only)
69+   -  ** Backward Compatible** : Works alongside existing callback-based ` sendRequest() ` 
70+   -  ** TypeScript Ready** : Full type safety with comprehensive TypeScript definitions
71+ -  ** Run Command** : ` node example/services/client/async-client-example.js ` 
72+ 
73+ ** Key API Differences** :
74+ 
75+ ``` javascript 
76+ client .sendRequest (request, (response ) =>  {
77+   console .log (' Response:'  , response .sum );
78+ });
79+ 
80+ try  {
81+   const  response  =  await  client .sendRequestAsync (request);
82+ 
83+   const  response  =  await  client .sendRequestAsync (request, { timeout:  5000  });
84+ 
85+   const  controller  =  new  AbortController ();
86+   const  response  =  await  client .sendRequestAsync (request, {
87+     signal:  controller .signal ,
88+   });
89+ 
90+   const  controller  =  new  AbortController ();
91+   const  response  =  await  client .sendRequestAsync (request, {
92+     timeout:  5000 ,
93+     signal:  controller .signal ,
94+   });
95+ 
96+   console .log (' Response:'  , response .sum );
97+ } catch  (error) {
98+   if  (error .name  ===  ' TimeoutError'  ) {
99+     console .log (' Request timed out'  );
100+   } else  if  (error .name  ===  ' AbortError'  ) {
101+     console .log (' Request was cancelled'  );
102+   } else  {
103+     console .error (' Service error:'  , error .message );
104+   }
105+ }
106+ ``` 
107+ 
51108### GetMap Service  
52109
53110#### Service Server (` service/getmap-service-example.js ` )  
@@ -129,6 +186,41 @@ ROS 2 services provide a request-response communication pattern where clients se
129186   Result: object { sum: 79n } 
130187    ``` 
131188
189+ ### Running the Async AddTwoInts Client Example  
190+ 
191+ 1 .  ** Prerequisites** : Ensure ROS 2 is installed and sourced
192+ 
193+ 2 .  ** Start the Service Server** : Use the same service server as above:
194+ 
195+    ``` bash 
196+    cd  /path/to/rclnodejs
197+    node example/services/service/service-example.js
198+    ``` 
199+ 
200+ 3 .  ** Start the Async Client** : In another terminal, run:
201+ 
202+    ``` bash 
203+    cd  /path/to/rclnodejs
204+    node example/services/client/async-client-example.js
205+    ``` 
206+ 
207+ 4 .  ** Expected Output** :
208+ 
209+    ** Service Server Terminal** : (Same as regular client)
210+ 
211+    ``` 
212+    Incoming request: object { a: 42n, b: 37n } 
213+    Sending response: object { sum: 79n } 
214+    -- 
215+     ``` 
216+ 
217+    ** Async Client Terminal** :
218+ 
219+    ``` 
220+    Sending: object { a: 42n, b: 37n } 
221+    Result: object { sum: 79n } 
222+     ``` 
223+ 
132224### Running the GetMap Service Example  
133225
1342261 .  ** Prerequisites** : Ensure ROS 2 is installed and sourced
@@ -236,8 +328,11 @@ This script automatically starts the service, tests the client, and cleans up.
236328
237329### Programming Patterns  
238330
239- -  ** Async/Await** : Modern JavaScript patterns for asynchronous operations
240- -  ** Callback Handling** : Response processing using callback functions
331+ -  ** Modern Async/Await** : Clean Promise-based service calls with ` sendRequestAsync() ` 
332+ -  ** Traditional Callbacks** : Response processing using callback functions with ` sendRequest() ` 
333+ -  ** Error Handling** : Proper error handling with try/catch blocks and specific error types (async only)
334+ -  ** Timeout Management** : Built-in timeout support to prevent hanging requests (async only)
335+ -  ** Request Cancellation** : AbortController support for user-cancellable operations (async only)
241336-  ** Resource Management** : Proper node shutdown and cleanup
242337-  ** Data Analysis** : Processing and interpreting received data
243338-  ** Visualization** : Converting data to human-readable formats
@@ -331,18 +426,23 @@ int8[] data
331426### Common Issues  
332427
3334281 .  ** Service Not Available** :
334- 
335429   -  Ensure the service server is running before starting the client
336430   -  Check that both use the same service name (` add_two_ints ` )
337431
3384322 .  ** Type Errors** :
339- 
340433   -  Ensure you're using ` BigInt() `  for integer values, not regular numbers
341434   -  Use ` response.template `  to get the correct response structure
342435
3434363 .  ** Client Hangs** :
344437   -  The client waits for service availability with a 1-second timeout
345438   -  If the service isn't available, the client will log an error and shut down
439+    -  For async clients, use timeout options: ` client.sendRequestAsync(request, { timeout: 5000 }) ` 
440+ 
441+ 4 .  ** Async/Await Issues**  (applies only to ` sendRequestAsync() ` ):
442+    -  ** Unhandled Promise Rejections** : Always use try/catch blocks around ` sendRequestAsync() ` 
443+    -  ** Timeout Errors** : Handle ` TimeoutError `  specifically for timeout scenarios (async only)
444+    -  ** Cancelled Requests** : Handle ` AbortError `  when using AbortController cancellation (async only)
445+    -  ** Mixed Patterns** : You can use both ` sendRequest() `  and ` sendRequestAsync() `  in the same code
346446
347447### Debugging Tips  
348448
@@ -354,6 +454,10 @@ int8[] data
354454
355455-  Both examples use the standard rclnodejs initialization pattern
356456-  The service server runs continuously until manually terminated
357- -  The client performs a single request-response cycle then exits
457+ -  The traditional client performs a single request-response cycle then exits
458+ -  The async client demonstrates multiple patterns and then exits
459+ -  ** New async/await support** : Use ` sendRequestAsync() `  for modern Promise-based patterns
460+ -  ** Full backward compatibility** : Existing ` sendRequest() `  callback-based code continues to work unchanged
461+ -  ** TypeScript support** : Full type safety available for async methods
358462-  Service introspection is only available in ROS 2 Iron and later distributions
359463-  BigInt is required for integer message fields to maintain precision
0 commit comments