【问题标题】:Is there a way to send response from server even if no callback is provided from client side?即使客户端没有提供回调,有没有办法从服务器发送响应?
【发布时间】:2020-02-17 10:09:04
【问题描述】:

问题说明

当我们使用.emit().send() 并且我们还想确认消息接收(所谓的acknowledgements)时,我们只需这样写:

socket.emit('someEvent', payload, callback);

这个问题的全部内容是callback 部分。这是很棒的东西,因为它通常允许将一些数据作为响应发送回,而不会发出额外的事件。服务器需要做的就是以适当的方式处理请求:

socket.on('someEvent', (payload, callback) => { 
   doSomeStuff(); 
   callback(someData);
);

当我们处理成功案例时,这很好用。但是在这些情况下我们该怎么办:

1) 回调不是从客户端发送的/回调不是一个函数,需要从服务器端响应类似 '错误:没有提供回调。用法:...'

例子:

客户端 - socket.emit('someEvent');socket.emit('someEvent', 1);

服务器端 - socket.on('someEvent', callback => callback());

2) 在处理请求时出现问题(例如,验证结果不成功),我们需要以如下方式报告:'未提供有效负载或无效'

例子:

服务器端 -

socket.emit('someEvent', payload, callback => { 
   checkPayload(); 
   callback(someData); 
});

客户端 - socket.on('someEvent', invalidPayload, callback);

问题:是否有一种机制可以从响应方创建自定义回调?

我的工作方式和解决方法

1) 至于缺少的回调或不是函数的回调,我得出的结论是,我只能验证它,然后仅在其有效性的情况下调用它。所以服务器端正在发生一些变化:

socket.emit('someEvent', callback => callback instanceof Function && callback()); //check callback correctness

优点:如果回调不是预期的函数,则不会出现内部错误。

缺点:如果回调无效,客户端将不会被注意到。

2) 至于我们需要发回一些错误的情况,我只找到了一种解决方法来返回一个特定的、事先约定的、虚假的值,比如null,这意味着不能返回任何数据。

socket.emit('someEvent', payload, callback => {  
   checkPayload();
   callback(someData || null); //send falsy, error-like value instead
});

优点:客户通过获取null 会发现一些错误。

缺点:在服务器端,没有简单的中间件函数来验证输入数据并在执行主要逻辑之前返回错误。

我已经考虑过使用中间件来实现所需的功能,但是还没有,可以说,“事件级中间件”,只有在整个 namespacesocket 级别上。我是否应该尝试在套接字级别按事件名称过滤事件以附加所需的功能并以next(new Error(...)); 之类的方式发送错误?在这种情况下,我猜可以使用error 事件监听。


socket.io / socket.io-client 使用的版本:2.3.0

【问题讨论】:

    标签: javascript node.js sockets npm socket.io


    【解决方案1】:

    1) 回调不是从客户端发送的/回调不是一个函数,需要从服务器端响应类似“错误:未提供回调”。用法:...'

    客户端和服务器必须就如何执行此操作达成一致。如果客户端不提供回调,则服务器参数将为undefined,以便您可以从服务器检测到。

    所以,正确的做法是:

    // client 
    socket.emit('someMsg', someData, function(response) {
        console.log(`Got ${response} from server`);
    });
    
    // server
    io.on('connection', socket => {
        socket.on('someMsg', (data, fn) => {
            console.log(`Got data ${data} from client, sending response`);
            // if client wants a response, send the response
            if (fn) {
                fn("got your data");
            }
        });
    });
    

    所以,如果客户端没有通过回调,那么服务器端的fn 将是undefined。所以,你在调用它之前测试它是正确的。

    2) 至于我们需要返回一些错误的情况,我只找到了一种解决方法,即返回一个特定的、事先约定的、虚假的值,比如 null,这样就意味着不能返回任何数据。

    是的,您必须事先同意如何发回错误。发回错误的最简洁方法可能是将您的响应包装在一个对象中并在该对象上使用.error 属性。

    // client 
    socket.emit('someMsg', someData, function(response) {
        if (response.error) {
            console.log(`Got error ${response.error} from server`);
        } else {
            console.log(`Got data ${response.data} from server`);
        }
    });
    
    // server
    io.on('connection', socket => {
        socket.on('someMsg', (data, fn) => {
            console.log(`Got data ${data} from client, sending response`);
            // if client wants a response, send the response
            if (fn) {
                // no error here
                fn({error: null, data: "Got your message"});
            }
        });
    });
    

    您在这里看到的是,socket.io 并不是真正的请求/响应类型协议,并且 socket.io 试图强行插入一些响应,您必须围绕它构建自己的结构。

    或者,如果有错误,您可以发送一个错误对象:

    // server
    io.on('connection', socket => {
        socket.on('someMsg', (data, fn) => {
            console.log(`Got data ${data} from client, sending response`);
            // if client wants a response, send the response
            if (fn) {
                // send an error here
                fn({error: new Error("xxx Error")});
            }
        });
    });
    

    在服务器端,没有简单的中间件函数可以在执行主逻辑之前验证输入数据并返回错误。

    我真的不明白您要使用中间件来做什么或验证什么?此数据存在的唯一位置是您的消息处理程序,因此您想要对客户端发送的内容进行的任何服务器端验证都需要在那里。您当然可以在发送响应之前进行验证。

    我是否应该尝试在套接字级别按事件名称过滤事件以附加所需的功能并以类似 next(new Error(...)); 的方式发送错误?在这种情况下,我猜可能会有错误事件监听的工作。

    Socket.io 不像 Express 那样工作,我真的不明白你为什么要让它这样工作。没有next() 参与接收socket.io 消息,所以我不确定你想在那里做什么。首次建立 socket.io 连接时有一个中间件选项,但通过该连接发送的后续消息没有。

    即使客户端没有提供回调,有没有办法从服务器发送响应?

    如果客户端不提供回调,那么向客户端发送回响应的唯一方法是发送另一条消息。但是,发送响应的全部意义在于,如果您有一个正在侦听并期待响应的合作客户端,那么如果客户端想要响应,他们也可以使用回调。如果客户端不想要响应并且不会编写任何代码来接收它,那么您无能为力。

    【讨论】:

    • @HlibDerbenov - 这回答了你的问题吗?
    • 所以总结一下:1)在没有提供回调的情况下强制服务器响应是没有用的(因为这根本不可能,也可能不符合 websockets 和确认的概念)和2) 可以将类似错误的信息附加到服务器的响应中(但前提是客户端想要获得响应)。我理解正确吗?
    • @HlibDerbenov - 是的。它就像任何 API 一样。如果客户端没有配置自己来查看响应或错误代码,那么服务器就没有办法让它做一些它没有被编码做的事情。但实际上,遵循 API、服务器设计和记录 API 的方式是客户端的责任。如果客户端选择不做正确的事情,那是客户端自己的问题,而不是服务器的问题。如果客户端选择忽略错误响应,那么这只是糟糕的客户端代码。你对此无能为力。
    • @HlibDerbenov - 这与使用 Google 的日历 API 提交新日历事件的客户端没有什么不同,并且客户端没有编码以识别错误响应并且无法意识到新日历事件何时没有被添加并返回错误。这只是糟糕的客户端代码 - Google 对此无能为力。
    猜你喜欢
    • 1970-01-01
    • 2017-09-11
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 2018-04-24
    • 1970-01-01
    相关资源
    最近更新 更多