我今天的问题与循环中的promises有关。在这里,我将放置我的代码,你可以看到它做了一些事情。首先,它在我的所有事件中循环,并将它在其中找到的日期拆分为3个字段,以将其插入到SQL数据库中。
总共填写2个表,一个包含日期,另一个包含实际事件。问题是当这个代码被执行时,它一直循环到结束并一次完成日期分配,然后它开始释放promises。这使我的函数插入x次相同的日期和事件(其中x是我的events数组的长度)。
现在,为什么会这样?我完全研究并实施了这个问题的承诺,但似乎仍然存在。有人可以向我解释我做错了什么吗?另外,你认为这段代码有点像“厄运的金字塔”吗?非常感谢提前!
events.forEach(function (event) {
// Simple date formatting
dayFormatted = event.day.split("_");
year = dayFormatted[0];
month = dayFormatted[1];
day = dayFormatted[2];
// Check if the row already exists ...
SQLCheckTableRow(`day`, year.toString(), month.toString(), day.toString()).then(function (skip) {
// ... if not it skips all this part
if (!skip) {
// Create, if it doesn't exist already, a date table that is going to be connected to all the events and fill it
SQLFillTable(`date, `null, "${year}" , "${month}" , "${day}", null`).then(function () {
let values = []
event.ons.forEach(function (on) {
on.states.forEach(function (event) {
values = [];
values.push(Object.keys(event.data).map(function (key) {
return event.data[key];
}));
SQLFillTable(`event`, values).then();
})
})
})
}
})
})
答案 0 :(得分:4)
当你在forEach循环中进行异步调用时,它不会等到调用完成。如果你想一个接一个地发起异步电话,你应该使用'来表示'循环而不是。如果要并行运行它们,可以将promises推送到数组,然后使用Promise.all(arrayOfPromises).then((result)=> {})获取promise调用的结果。这里的结果将是异步调用的数组,其顺序与promise数组相同。
如果你想让你的代码更容易阅读,而不是有厄运的金字塔,那么习惯使用async..await。在这里,我使用for..of循环重构了你的代码。如上所述,如果要并行运行异步调用,请使用Promise.all。
async function queryTable() {
for (let event of events) {
// Simple date formatting
let dayFormatted = event.day.split("_");
let year = dayFormatted[0];
let month = dayFormatted[1];
let day = dayFormatted[2];
try{
let skip = await SQLCheckTableRow(`day`, year.toString(), month.toString(), day.toString());
if (!skip) {
// Create, if it doesn't exist already, a date table that is going to be connected to all the events and fill it
await SQLFillTable('date', null, year, month , day, null);
for (let on of event.ons) {
const values = [];
values.push(Object.keys(on.data).map(key => on.data[key]));
await SQLFillTable('event', values);
}
}
} catch(err) {
console.error(err);
}
}
}