Skip to content

Commit

Permalink
Add advertiseAsync method to Service (#698)
Browse files Browse the repository at this point in the history
  • Loading branch information
EzraBrooks committed Mar 19, 2024
1 parent 29b14ce commit f8d6dde
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/core/Service.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,37 @@ export default class Service extends EventEmitter {

this.ros.callOnConnection(call);
}

/**
* An alternate form of Service advertisement that supports a modern Promise-based interface for use with async/await.
* @param {(request: TRequest) => Promise<TResponse>} callback An asynchronous callback processing the request and returning a response.
*/
advertiseAsync(callback) {
if (this.isAdvertised) {
throw new Error('Cannot advertise the same Service twice!');
}
this.ros.on(this.name, async (rosbridgeRequest) => {
/** @type {{op: string, service: string, values?: TResponse, result: boolean, id?: string}} */
let rosbridgeResponse = {
op: 'service_response',
service: this.name,
result: false
}
try {
rosbridgeResponse.values = await callback(rosbridgeRequest.args);
rosbridgeResponse.result = true;
} finally {
if (rosbridgeRequest.id) {
rosbridgeResponse.id = rosbridgeRequest.id;
}
this.ros.callOnConnection(rosbridgeResponse);
}
});
this.ros.callOnConnection({
op: 'advertise_service',
type: this.serviceType,
service: this.name
});
this.isAdvertised = true;
}
}
28 changes: 28 additions & 0 deletions test/service.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { it, describe, expect } from 'vitest';
import { Service, Ros } from '../';

describe('Service', () => {
const ros = new Ros({
url: 'ws://localhost:9090'
});
it('Successfully advertises a service with an async return', async () => {
const server = new Service({
ros,
serviceType: 'std_srvs/Trigger',
name: '/test_service'
});
server.advertiseAsync(async () => {
return {
success: true,
message: 'foo'
}
});
const client = new Service({
ros,
serviceType: 'std_srvs/Trigger',
name: '/test_service'
})
const response = await new Promise((resolve, reject) => client.callService({}, resolve, reject));
expect(response).toEqual({success: true, message: 'foo'});
})
})

0 comments on commit f8d6dde

Please sign in to comment.