我正在尝试编写一个 GUI 前端,它使用服务来获取有关系统的数据。我使用 net.Socket
作为其客户端。我希望能够访问在其他模块的数据事件处理程序中分配的某些变量,但在回调函数完成后分配不会保留。
有问题的代码:
client.on('data', (data) => {
var array = [...data];
array.splice(0,2);
for (var i=0;i<array.length;i++) {
dataInBuffer = dataInBuffer + String.fromCharCode(array[i]);
}
console.log(dataInBuffer);
if (dataInBuffer.startsWith('batStat')) {
let lastBatteryJSON = JSON.parse(dataInBuffer.split(';')[1]);
module.exports.hasBattery = lastBatteryJSON.hasBattery == 'true';
module.exports.isCharging = lastBatteryJSON.isCharging == 'true';
module.exports.lastBatteryReading = parseFloat(lastBatteryJSON.batteryLife);
}
dataInBuffer = '';
});
这三个导出的变量赋值实际上不起作用,这些变量总是保持未定义状态或者在函数之外保持默认值。我尝试使用 Promise 来解决这个问题,但得到了相同的结果。我很茫然,找不到解决此问题的任何其他问题或论坛帖子。
编辑 我无法选择将依赖于这些变量的代码移动到回调中。为了做到这一点,我必须等待每一帧的数据并因此淹没服务器。
最佳答案
正如苹果评论的那样;您可以导出一个对象并在每次接收数据时改变它:
const data = {};
client.on('data', (data) => {
var array = [...data];
array.splice(0, 2);
for (var i = 0; i < array.length; i++) {
dataInBuffer = dataInBuffer + String.fromCharCode(array[i]);
}
console.log(dataInBuffer);
if (dataInBuffer.startsWith('batStat')) {
let lastBatteryJSON = JSON.parse(dataInBuffer.split(';')[1]);
//mutate the data object
data.hasBattery = lastBatteryJSON.hasBattery == 'true';
data.isCharging = lastBatteryJSON.isCharging == 'true';
data.lastBatteryReading = parseFloat(lastBatteryJSON.batteryLife);
}
dataInBuffer = '';
});
//export the data object
module.exports.batteryData = data;
或者,当 certainPerformance 回答时,您可以让调用者决定何时询问信息并提供 promise 。
这是一定性能答案的扩展版本,它也监听错误,因此可以拒绝 promise ,并在解决或拒绝 promise 时清理事件监听器:
//wrapper for client.on to add and remove event listeners
const listeners = (function(){
var listenerCounter = -1;
const listeners = [];
const triggerEvent = event => data =>{
listeners.filter(
listener=>listener[2] === event
).forEach(
listener=>listener[1](data)
);
};
client.on('data', triggerEvent("data"));
client.on('error', triggerEvent("error"));//assuming you have an error event
return {
add:(event,fn)=>{
listenerCounter = listenerCounter + 1;
if(listenerCounter>1000000){
listenerCounter=0;
}
listeners.push([listenerCounter,fn,event]);
return listenerCounter;
},
remove:num=>{
listeners = listeners.filter(
listener=>{
num !== listener[0];
}
)
}
}
}());
//convert data to object or false
const getObjectFromData = data => {
var array = [...data];
var dataInBuffer="";
array.splice(0,2);
for (var i=0;i<array.length;i++) {
dataInBuffer = dataInBuffer + String.fromCharCode(array[i]);
}
console.log(dataInBuffer);
if (dataInBuffer.startsWith('batStat')) {
let lastBatteryJSON = JSON.parse(dataInBuffer.split(';')[1]);
return {
hasBattery : lastBatteryJSON.hasBattery == 'true',
isCharging : lastBatteryJSON.isCharging == 'true',
lastBatteryReading : parseFloat(lastBatteryJSON.batteryLife)
};
}
return false;
}
//export this function
const getBatteryData = () =>
new Promise((resolve,reject) => {
const removeListeners = ()=>{
listeners.remove(okId);
listeners.remove(errorId);
}
const okId = listeners.add(
"data",
data=>{
const resultObject = getObjectFromData(data);
if(resultObject){
resolve(data);
removeListeners();//clean up listeners
}else{
//not sure of on data is triggered multiple times by client.on.data
// if it is then at what point do we need to reject the returned promise?
}
}
)
const errorId = listeners.add(
"error",
error=>{
reject(error);
removeListeners();//clean up listeners
}
)
});
//you can call getBatteryData like so:
//getBatteryData()
// .then(batteryData=>console.log(batteryData))
// .catch(error=>console.warn("an error getting battery data:",error))
关于javascript - 如何分配异步函数中同步作用域中定义的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49889672/