-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add socket.request()
as promise wrapper around callbacks
#4175
Comments
The implementation of the feature can be straightforward: class Socket {
constructor() {
this.buildError = err => this.io.buildError(err);
}
errorBuilder(fn) {
this.buildError = fn;
}
request(...args) {
return new Promise((resolve, reject) => {
args.push((err, response) => {
if (err) {
reject(this.buildError(err));
} else {
resolve(response);
}
});
});
}
reply(event, handler) {
this.on(event, (...args) => {
let cb = args.at(-1);
if (typeof cb === 'function') {
cb = args.pop();
} else {
cb = (err) => this._error(err);
}
let resolve = res => cb(null, res);
let reject = err => cb(err);
try {
let res = handler.call(this, ...args);
if (res && res.then) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (e) {
reject(e);
}
});
}
} |
Yes, that was on my mind too, but then we'd have to include a polyfill for browsers that do not support Promises.. See also: #4144 |
Wouldn't it be an option to not include a polyfill and leave it up to the user? If the user targets browsers that don't support promises, he would either:
|
@sebamarynissen that makes sense 👍 Let's keep this issue open, to see if other users want this functionality to be built-in. |
I would like this functionality, and it also helps to write code and tests more readable using async await syntax. But I'm not convinced by the name
and in the same way For example this: socket.io/examples/basic-crud-application/server/test/todo-management/todo.tests.ts Lines 165 to 200 in 3b7ced7
to something like this; describe('update todo', () => {
it('should update a todo entity', async () => {
const todoId = 'c7790b35-6bbb-45dd-8d67-a281ca407b43';
todoRepository.save({
id: todoId,
title: 'lorem ipsum',
completed: true,
});
const todoUpdated = {
id: todoId,
title: 'dolor sit amet',
completed: true,
};
const onTodoUpdated = jest.fn();
otherSocket.on('todo:updated', onTodoUpdate);
await socket.emitWithAck('todo:update', todoUpdated);
const storedEntity = await todoRepository.findById(todoId);
expect(storedEntity).toEqual(todoUpdated);
expect(onTodoUpdated).toBeCalledWith(todoUpdated);
});
}); Is there any plan to implement it? Thank you. |
This commit adds some syntactic sugar around acknowledgements: - `emitWithAck()` ```js try { const responses = await io.timeout(1000).emitWithAck("some-event"); console.log(responses); // one response per client } catch (e) { // some clients did not acknowledge the event in the given delay } io.on("connection", async (socket) => { // without timeout const response = await socket.emitWithAck("hello", "world"); // with a specific timeout try { const response = await socket.timeout(1000).emitWithAck("hello", "world"); } catch (err) { // the client did not acknowledge the event in the given delay } }); ``` - `serverSideEmitWithAck()` ```js try { const responses = await io.timeout(1000).serverSideEmitWithAck("some-event"); console.log(responses); // one response per server (except itself) } catch (e) { // some servers did not acknowledge the event in the given delay } ``` Related: - #4175 - #4577 - #4583
For future readers:
io.on("connection", async (socket) => {
// without timeout
const response = await socket.emitWithAck("hello", "world");
// with a specific timeout
try {
const response = await socket.timeout(1000).emitWithAck("hello", "world");
} catch (err) {
// the client did not acknowledge the event in the given delay
}
}); Have a great day! |
This commit adds some syntactic sugar around acknowledgements: - `emitWithAck()` ```js try { const responses = await io.timeout(1000).emitWithAck("some-event"); console.log(responses); // one response per client } catch (e) { // some clients did not acknowledge the event in the given delay } io.on("connection", async (socket) => { // without timeout const response = await socket.emitWithAck("hello", "world"); // with a specific timeout try { const response = await socket.timeout(1000).emitWithAck("hello", "world"); } catch (err) { // the client did not acknowledge the event in the given delay } }); ``` - `serverSideEmitWithAck()` ```js try { const responses = await io.timeout(1000).serverSideEmitWithAck("some-event"); console.log(responses); // one response per server (except itself) } catch (e) { // some servers did not acknowledge the event in the given delay } ``` Related: - socketio#4175 - socketio#4577 - socketio#4583
This commit adds some syntactic sugar around acknowledgements: - `emitWithAck()` ```js try { const responses = await io.timeout(1000).emitWithAck("some-event"); console.log(responses); // one response per client } catch (e) { // some clients did not acknowledge the event in the given delay } io.on("connection", async (socket) => { // without timeout const response = await socket.emitWithAck("hello", "world"); // with a specific timeout try { const response = await socket.timeout(1000).emitWithAck("hello", "world"); } catch (err) { // the client did not acknowledge the event in the given delay } }); ``` - `serverSideEmitWithAck()` ```js try { const responses = await io.timeout(1000).serverSideEmitWithAck("some-event"); console.log(responses); // one response per server (except itself) } catch (e) { // some servers did not acknowledge the event in the given delay } ``` Related: - socketio#4175 - socketio#4577 - socketio#4583
I noticed that in the 4.4.0 release, a
timeout
flag was added:Interestingly I implemented similar logic in an application of mine by patching client-side sockets, but I combined it with promises as well. Something like
where the promise times out after a fixed amount of time if the server did not acknowledge.
As a result, I was wondering whether it would a nice feature to add to the library as well. The api would look something like
This could be accompanied by a
reply()
andreplyAny()
method as well of course, which looks something like this and hence hides the callbacks from the user alltogether:Additionally I think it might be useful to have a way of resurrecting errors as well, but I'm not sure how the api can look like. Perhaps something like
or
where
socket.errorBuilder
can be used to override for that socket.As always, I'd be happy to create a PR for this should you decide that it is a feature that is desirable to have in the library. In my opinion it fits nicely in the trend that callbacks are more and more being replaced by promises.
The text was updated successfully, but these errors were encountered: