值在 ES6 承诺中的 for 循环中返回为"未定义"



所以我目前正在编写一个清单应用程序,并且在将值插入数据库中时遇到了一些问题。 发生的情况是,我得到一个项目对象列表,其中包含有关该特定项目的信息。 然后,我将这些项目推送到一个列表中并调用一个套接字,该套接字运行 for 循环将这些项目插入我的数据库中,但是当我查看这些项目应该所在的表时,它们的所有值都设置为undefined

我的项目对象如下所示:

let ItemObject = {
ID: id,
Name: name,
Qty: qty
}

调用数据库序列的承诺:

export const insertItem = async (list) => {
return new Promise(async (resolve, reject) => {
try {
console.log(list);
for(let i = 0; i < list.length; i++){
const writeSolutionData = `INSERT INTO database (ID, Name, Qty) VALUES ("${list.ID}", "${list.Name}", "${list.Qty});`;
const response = await db(writeSolutionData, "Inserting Item");
resolve(response);   
}
} catch (e) {
console.log("ERROR database.insertItem: " + e);
reject(e);
}
});
};

这是被调用的套接字:

socket.on('insertItem', async (data, callback) => {        
try {
const results = await insertItem(data);
callback(true);
}
catch (error) {
callback(false);
}
});

当我控制台在 for 循环之前记录列表时,我得到了我期望的输出,但是在此承诺完成后,我的数据库中返回的数据undefined. 我也没有收到来自回调的错误。 ES6 承诺的想法对我来说仍然是新的,所以如果我在这里的内容不正确,请原谅我。 这是我第一次尝试在这样的异步承诺中实现 for 循环,所以

第一次这不起作用对我来说并不奇怪。如果有人对我做错了什么有任何建议,我将不胜感激。 谢谢!

insertItem

不必是async函数。只需返回Promiseasync它使用 promise 回调,只有在该范围内才需要await关键字。

async函数会自动返回Promise,但您需要一个Promise构造函数才能使用resolvereject方法。它基本上是相同的,但具有不同的语法和选项。

另外,我注意到您的循环有错误。您尝试从数组中选择list.IDlist.Namelist.Qty,但应该从数组中的项目中获取值。

我还在查询字符串的末尾发现了一个缺失"

export const insertItem = (list) => new Promise(async (resolve, reject) => {
try {
list.forEach(item => {
const writeSolutionData = `INSERT INTO database (ID, Name, Qty) VALUES ("${item.ID}", "${item.Name}", "${item.Qty}");`;
const response = await db(writeSolutionData, "Inserting Item");
resolve(response);   
});
} catch (e) {
console.log("ERROR database.insertItem: " + e);
reject(e);
}
});

补遗

使用Promise.all更新了答案。@wizloc建议。

这将循环所有项目并从db()函数返回 promise,并将它们存储到一个新数组中。 然后,每当数组中的所有承诺都已满时,Promise.all将解析并返回单个数组中每个承诺的值。

export const insertItem = (list) => new Promise(async (resolve, reject) => {
try {
const responses = list.map(item => {
const writeSolutionData = `INSERT INTO database (ID, Name, Qty) VALUES ("${item.ID}", "${item.Name}", "${item.Qty}");`;
return db(writeSolutionData, "Inserting Item");
});
const results = await Promise.all(responses);
resolve(results);
} catch (e) {
console.log("ERROR database.insertItem: " + e);
reject(e);
}
});

我不熟悉什么

const writeSolutionData = `INSERT INTO database (ID, Name, Qty) VALUES ("${list.ID}", "${list.Name}", "${list.Qty}");`;
const response = await db(writeSolutionData, "Inserting Item");

实际上确实如此(除了显而易见的(,但由于db(writeSolutionData, "Inserting Item")是等待的,因此它会返回一个承诺。正如我在评论中提到的,您的原始代码在循环的第一次迭代中解析,因此如果您需要访问从您的承诺返回的值,您会发现您只能访问第一个值。您问为什么需要这些值,因为您可以在之后查询它们,我无法回答这个问题,因为我对您的项目一无所知,您计划在插入数据后如何处理数据等。但是承诺的另一个好处是通过链接.then().catch()来处理错误。

您可以将整个 insertData 方法简化为以下内容

socket.on('insertItem', async (data, callback) => {
const promises = data.map(x =>
db(`INSERT INTO database (ID, Name, Qty) VALUES ("${x.ID}", "${x.Name}", "${x.Qty});`)
)
Promise.all(promises)
.then(values => {
// Do something with values array
callback(true)
})
.catch(error => {
// Error handling
callback(false)
})
});

这样做将确保仅在成功插入所有项目时才调用callback(true)如果任何项目失败,则会出错(callback(false)(。

我认为insertItem不是异步函数,因为它不包含await...

export const insertItem = /*async <- remove it */ (list) => {
return new Promise(async (resolve, reject) => {
try {
console.log(list);
for(let i = 0; i < list.length; i++){
const writeSolutionData = `INSERT INTO database (ID, Name, Qty) VALUES ("${list.ID}", "${list.Name}", "${list.Qty});`;
const response = await db(writeSolutionData, "Inserting Item");
resolve(response);   
}
} catch (e) {
console.log("ERROR database.insertItem: " + e);
reject(e);
}
});
};

最新更新