sql - 来自异步函数的 Node.js Express 结果集不可用作函数值
问题描述
在 Node Express 应用程序中,替代产品通过产品 ID 连接到产品。替代产品(在单独的表中)与 ProductAlternatives.AlternativeProductId=Products.Id 上的产品正确连接。我正在尝试生成一个嵌套的 JSON 结构,其中替代产品(如果可用)显示在一个单独的数组中。
我得到的结果是一个扁平的 JSON 结构,如下所示:
[
{
"Id": 1,
"ProductName": "2 Zits My Style",
"Description": "2 zits | stof | Stof grof geweven lichtgrijs",
"Price": "579.00",
"Picture": "~/UserImages/8195299-254-02.jpg",
"CatID": 5,
"alternateproducts": {}
},
{
"Id": 4,
"ProductName": "Slaapbank Hervik",
"Description": "Cubos 50 lever",
"Price": "1.499.00",
"Picture": "~/UserImages/8202978-06.jpg",
"CatID": 11,
"alternateproducts": {}
},
所以,没有替代产品。第一个产品的属性 alternateproducts 应该正好包含 2 个替代产品,如下所示:
[
{
"Id": 1,
"ProductName": "2 Zits My Style",
"Description": "2 zits | stof | Stof grof geweven lichtgrijs",
"Price": "579.00",
"Picture": "~/UserImages/8195299-254-02.jpg",
"CatID": 5,
"alternateproducts": {
[
{
"Id": 24,
"ProductName": "Zitbank Ravenia",
"Description": "2 zits | stof | Stof ribstof taupe",
"Price": "1.139.00",
"Picture": "~/UserImages/8192530-94-02.jpg",
"CatID": 5
},
{
"Id": 25,
"ProductName": " Zitbank Gino",
"Description": "2 zits | Stof velours okergeel",
"Price": "499.00",
"Picture": "~/UserImages/8194150-01.jpg",
"CatID": 5
}
]
}
},
{
"Id": 4,
"ProductName": "Slaapbank Hervik",
"Description": "Cubos 50 lever",
"Price": "1.499.00",
"Picture": "~/UserImages/8202978-06.jpg",
"CatID": 11
}
代码如下:
var structured;
// Application
app.route('/products')
// GET endpoint
.get(cors(), function(req, res) {
// create Request object
var request = new appmodule.sql.Request();
// query to the database and get all the records
request.query('SELECT * FROM Products', function (err, recordset) {
if (err) console.log(err)
GenerateStructuredJSON(recordset);
res.json(structured);
});
});
function GenerateStructuredJSON(recordset) {
var products = recordset.recordset;
structured = getNestedProducts(products);
function getNestedProducts(prod) {
for(var i = 0; i < prod.length; ++i) {
var productId = prod[i].Id;
var alternativeproducts = getAlternativeProducts(productId);
console.log(alternativeproducts); // logging nothing but Promise { <pending> }
if(alternativeproducts) {
prod[i].alternateproducts = alternativeproducts;
}
}
return prod;
}
}
async function getAlternativeProducts(prodID) {
const rs = await new Promise(function(resolve, reject,) {
var request = new appmodule.sql.Request();
request.input('prodid', sql.Int , prodID);
request.query('SELECT Products.* FROM Products ' +
'RIGHT JOIN ProductAlternatives ON ProductAlternatives.AlternativeProductId=Products.Id ' +
'WHERE ProductAlternatives.ProductId=@prodid', function(err, res) {
if (err) throw err
resolve(res.recordset);
})
});
console.log(rs); // logging json product structures correctly
return rs;
}
奇怪的是,来自异步函数的结果集 rs 使用 console.log(rs); 正确记录,但是一旦它连接到函数 getNestedProducts 中的 var Alternativeproducts,它只记录空Promise { <pending> }
的。所以结果集当时似乎丢失或不可用。
解决方案
原因是 node.js 中的 async 函数只是一个 Promise。线
var alternativeproducts = getAlternativeProducts(productId);
将 Promise 分配给替代产品。
您可以使函数 GenerateStructuredJSON(recordset) 异步,然后在您的主函数中,您可以
await GenerateStructuredJSON(recordset)
但是随后您将需要等待为每个产品创建的 getAlternativeProducts 的所有 Promises。
我认为更好的方法是使用 LEFT OUT jOIN 让一个 sql 包含替代产品作为结果的一部分。然后,您只需将生成的 JSON 结构化为预期的格式。
还有,之后
if (err) console.log(err)
它不应该继续,即:
if (err) {
console.log(err);
return res.json(err);
}
推荐阅读
- r - 从命令行运行 R 笔记本
- python - 如何从 pyspark 中删除数据帧来管理内存?
- hadoop - Cloudera 快速入门 CDH 5.15 集群运行缓慢
- node.js - 如何在 AWS Lambda 函数中使用异步库调用?
- excel - 在 Excel 中将原始数字转换为时间戳
- c# - 什么会导致 Base64 解码抛出 FormatException
- r - 如何编写一个函数来以相同的方式操作多个数据帧?
- puppeteer - 使用 puppeteer 将 ElementHandle 转换为 DOM 元素?
- rust - 通用特征和 slice::sort_by 的终身问题
- json - 使用 Excel 查询从 API (Json) 处理分页