Closed ldegen closed 11 months ago
@ldegen thanks for submitting the issue and investigating the details, I will take a look later. Please feel free to open a PR if you are interested in fixing it, thanks!
@minggangw I think I have an idea how to fix it without breaking existing code: Simply wrap the return value of callback in a Promise.resolve(...)
and then wait for this to resolve before continuing. That should tick all the boxes, I think. Testing this now, if it works, I'll create a PR.
@minggangw I think I have an idea how to fix it without breaking existing code: Simply wrap the return value of callback in a
Promise.resolve(...)
and then wait for this to resolve before continuing. That should tick all the boxes, I think. Testing this now, if it works, I'll create a PR.
Thanks, I have approved the PR and am planning to make a hotfix release once your PR merged.
@ldegen your fix has landed onto latest v0.23.3 https://www.npmjs.com/package/rclnodejs/v/0.23.3 !
Description
It seems
Node.createService
has some problems when dealing with a asynchronous callback functions.Steps To Reproduce
I run the above code using node (20.10.0).
Then on a second terminal, I run
ros2 service call /bug/get_answer rclnodejs_bug/srv/GetAnswer
Expected Behavior
Actual Behavior
Workaround
Remove the
async
keyword from the callback. If necessary, move code that usesawait
and friends to a separate function.What I think is the problem
Have a look at this piece of code in service.js:
https://github.com/RobotWebTools/rclnodejs/blob/4576609fa1941b2694eb1068eaccacf17cecf151/lib/service.js#L77-L84
It seems that the code expects callback to either return a response synchronously, or to call
response.send(...)
. The if condition in line 80 tries to determine if the latter has not happened yet and if in fact there is a return value. The problem here is that for anasync
function, there is always a return value: A Promise.In my toy example above, this Promise object gets misinterpreted as an actual response value. Also, the check for
response.sent
does not help in this case, because the response is send asynchronous. So at the time that the if condition is evaluated, it has in fact not been sent yet.The resulting behavior from the service module is that it will try to send a second response, ultimately failing (because the returned value is not a response, but a Promise resolving to undefined), and causing a considerable amount of confusion in for example a mocha test suite that was executing this.
As for possible mitigations, I am not sure. Maybe it would help to simply ignore the return value? I think this is undocumented behavior anyway?.