我正试图在$(document).ready()函数中动态地将数据从一个对象映射到另一个对象,问题是只要它想,它就能工作,整个代码中的console.log有时能工作,有时不能。
var newBtnsObj = {};
$(document).ready(() => {
robots.forEach((robot) => {
newBtnsObj[robot.Name] = {};
newBtnsObj[robot.Name].Buttons = {};
console.log(newBtnsObj);
Object.keys(robot.ConfigData).forEach((dataType) => {
if (dataType === DataTypes.IO) {
Object.values(robot.ConfigData[`${dataType}`]).forEach((IOData) => {
if (IOData.length > 0) {
IOData.forEach((s) => {
console.log("HI");
newBtnsObj[robot.Name].Buttons[s.HtmlID] = {
DataType: dataType,
ID: s.ID,
Val: null,
};
});
}
});
} else {
Object.values(robot.ConfigData[`${dataType}`]).forEach((data) => {
console.log("doublehi");
newBtnsObj[robot.Name].Buttons[data.HtmlID] = {
DataType: dataType,
ID: data.ID,
Val: null,
};
});
}
});
});
});
机器人 是一个数组,每当有人连接到页面的时候,就会在socket.io事件里面生成,我在后台使用NodeJS发出 "config "数据,这个数据是在创建对象的时候使用的,当有人打开页面的时候,首先发出的就是它。我是在本地打开页面,并将页面和服务器托管在本地。
socket.on("config", (config) => {
config.forEach((robot) => {
robots.push(new Robot(robot.Name, robot.configData, robot.Events));
});
我在HTML中加载文件的顺序是先是socket文件,然后是带有$(document).ready代码的文件。
问题是newBtnsObj有时创建,有时不创建,如果我添加任何新代码并刷新页面,它只在第一次刷新时工作,然后它又是一个空对象。但即使这样也不是每次都能成功,我甚至不能100%重现。
为了完整起见,我添加了完整的代码,但是即使我删除newBtnsObj的创建,只留下控制台的log("hi"),我也有同样的问题,所以问题不在对象创建本身(如果我复制并粘贴代码到浏览器控制台,它可以完美地工作)。所以,即使其任由其这样做,仍然存在同样的问题。
$(document).ready(() => {
robots.forEach((robot) => {
Object.keys(robot.ConfigData).forEach((dataType) => {
if (dataType === DataTypes.IO) {
Object.values(robot.ConfigData[`${dataType}`]).forEach((IOData) => {
if (IOData.length > 0) {
IOData.forEach((s) => {
console.log("HI");
});
}
});
} else {
Object.values(robot.ConfigData[`${dataType}`]).forEach((data) => {
console.log("doublehi");
});
}
});
});
});
另外,我认为问题可能出在,我试图在初始套接字事件中接收到的配置创建robots数组之前就使用它,所以我试着把代码放在事件本身,这样它就能在接收到事件后立即执行,并且成功了。很明显就是这个问题,我该如何解决呢?是不是只有把代码放在socket事件中,如果要提取代码,就要再做一个内部事件让代码知道机器人数组准备好了?
看来你给自己编了一个 竞赛条件 在那里。所以你的jQuery在页面加载的时候就会被执行,不管你的 robots
对象的存在与否。但是对象的生成也与连接和网络时间有关。所以你的脚本只有在生成的速度比你的页面加载速度快的情况下才能正常运行。
现在你可能会问,如果你把代码复制到生成对象的下面,它为什么会不工作呢?这也是一个竞赛条件。jQuery ready状态下的代码只有在页面加载后才会被执行。如果你把代码贴在另一个脚本里面,比如对象生成,就绪状态可能会在页面已经加载的时候被注册。所以它永远不会被执行,因为你注册的太晚了。
所以你需要做的是,确保代码只在生成完成后执行。也许通过使用回调、事件或其他方法。但现在,你有两个相关的脚本,它们可以随时运行,没有人等待对方。)
顺便说一下,只是一个提示:使用 $(document).ready(() => {})
不是最佳做法,也是过时的。有一个简写。而且你应该使用 jQuery
而不是 $
用于调用它,因此你的脚本将在 noConflict
模式了。所以,本体使用 jQuery(($) => {})
.