var data = bar();
function bar() {
var result;
socket.emit('message', 'test');
socket.on('msg', function(message) {
result = message;
});
return result;
}
在这里,结果值为undefined
。如何将从socket.on
函数获取的值分配给result
变量并返回?
这是我收到socket.io
消息事件的另一端。
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket, username) {
socket.on('message', function(message) {
var result = 'test value'
socket.emit('msg', result);
});
});
尝试以确认的方式返回对象。
io.sockets.on('connection', function (socket) {
socket.on('message', function(message, ackCallback) {
console.log("server received message", message);
var result = tools.execute(message);
console.log(typeof(result)); // result is returned a object
ackCallback(result);
});
});
P.S。我试图传递一个简单的对象
var result = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
ackCallback(result);
该对象的结果值正在传递。
tools.execute(message);正在返回此对象。哪个没有通过ackCallback传递。
{uuid:“ 155C75EA-CB23-4172-85EB-3E256A271D8D”, 名称: '', 类型:“ Object3D”, 父级:null, 儿童: [{uuid:“ D778A19B-F935-4B06-8536-54494BC5F920”, 名称: '', 类型:“网格”, 家长:[通告], 孩子:[], 上:[对象], 位置:[对象], 旋转:[对象], 四元数:[对象], 比例尺:[对象], 矩阵:[对象], matrixWorld:[Object], matrixAutoUpdate:是, matrixWorldNeedsUpdate:否, 图层:[对象], 可见:正确, castShadow:否, receiveShadow:否, frustumCulled:正确, renderOrder:0, 用户数据: {}, 几何:[对象], 材料:[对象], drawMode:0}, {uuid:“ 9FD1CACF-6A2B-4932-8FA2-B0A4AF618F8D”, 名称: '', 类型:“网格”, 家长:[通告], 孩子:[], 上:[对象], 位置:[对象], 旋转:[对象], 四元数:[对象], 比例尺:[对象], 矩阵:[对象], matrixWorld:[Object], matrixAutoUpdate:是, matrixWorldNeedsUpdate:否, 图层:[对象], 可见:正确, castShadow:是的, receiveShadow:否, frustumCulled:正确, renderOrder:0, 用户数据: {}, 几何:[对象], 材料:[对象], drawMode:0}], 上:{x:0,y:1,z:0}, 位置:{x:0,y:0,z:0}, 回转: {_x:0, _y:0, _z:0, _order:“ XYZ”, onChangeCallback:[功能:onRotationChange]}, 四元数: {_x:0, _y:0, _z:0, _w:1 onChangeCallback:[函数:onQuaternionChange]}, 比例尺:{x:1,y:1,z:1}, 矩阵:{元素:Float32Array [1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1]}, matrixWorld:{元素:Float32Array [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}, matrixAutoUpdate:是, matrixWorldNeedsUpdate:否, 图层:{mask:1}, 可见:正确, castShadow:否, receiveShadow:否, frustumCulled:正确, renderOrder:0, userData:{}}
答案 0 :(得分:3)
您不能“使Javascript等待”来发生异步事件。那不是Javascript的工作方式。这是一个事件驱动的体系结构,根本无法正常工作。
此外,当通过某种异步操作获得该值时,无法直接从该函数返回该值。该函数将在值准备好很久之前返回。您可以查看为何如此的详细信息,以及this canonical answer中有关该常规主题的一些选项。
处理异步结果的现代方法是返回一个将在事件发生时解决的承诺,然后调用方可以使用该承诺来获得最终结果。
function bar(data, timeout = 10000) {
return new Promise((resolve, reject) => {
let timer;
socket.emit('message', data);
function responseHandler(message) {
// resolve promise with the value we got
resolve(message);
clearTimeout(timer);
}
socket.once('msg', responseHandler);
// set timeout so if a response is not received within a
// reasonable amount of time, the promise will reject
timer = setTimeout(() => {
reject(new Error("timeout waiting for msg"));
socket.removeListener('msg', responseHandler);
}, timeout);
});
}
bar().then(message => {
// you can use message here and only in here
});
我在这里显示的是一个更高级的版本,该版本也实现了超时,因此,如果在一定时间内未收到响应,则承诺将被拒绝。这是为了避免创建可能永远存在,永远不会得到回应,因此永远无法解决的承诺。
注意:如果要使用socket.io实现某种类型的请求/响应,则可以从第一条消息中获得直接响应,这是使用socket.io响应特定请求的更好方法。您可以看到ack
回调选项如何用于socket.emit()
here in the doc。要使用它,您需要连接两端的合作。您发送一条消息并指定一个ack
回调。然后,消息的接收者提供ack
回调将接收的一些ack
数据。如果您同时对同一封邮件提出了其他要求,这将是对您邮件的直接响应,不会使您感到困惑。对于socket.io中的请求/响应,这是首选的体系结构。为了向您展示如何实现它的完整代码示例,我们将必须查看代码的另一端接收到socket.io message
事件。
好的,既然您已经显示了连接的另一端,则可能应该使用socket.io的ack
响应功能:
function bar(timeout = 10000) {
return new Promise((resolve, reject) => {
console.log("client sending message 'test');
socket.emit('message', 'test', function(response) {
console.log("client got ack response", response);
resolve(response);
});
});
}
bar().then(message => {
// you can use message here and only in here
console.log("response from bar(): ", message);
});
服务器端:
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
socket.on('message', function(message, ackCallback) {
console.log("server received message", message);
var result = 'test value'
console.log("server sending back result", result);
ackCallback(result);
});
});
P.S。您的服务器端代码在此处显示了username
参数:
io.sockets.on('connection', function(socket, username) {
没有这样的username
参数传递给该事件处理程序,因此我不确定您从何处获得该参数。您的代码并未真正使用该代码,因此我将其删除(因为它仍然无效)。