[英]Loading Records from a child table with a node.js API
好,
我对node.js和回调函数的整个概念还很陌生,我一直在绞尽脑汁试图弄清楚这一点。 也许你们中的一些人/女孩可以提供帮助。
因此,基本设置是我在前端有一个使用API作为数据源的React / Redux应用程序。 在前面,我想一次加载一些产品并加载其所有图像,然后我有一个Product组件,它显示一个产品,并显示一个图片库(这就是为什么我需要所有产品图像的原因一旦)
当我请求http://myapi.com/randomproducts/时,我试图编写一个API,它将从MySQL数据库返回指定数量的随机产品。 我有那部分。 这就是让我感到困惑的部分……我在该系列产品中返回的每个产品都有与之相关的未知图像。 我想同时加载它们,以便我返回的内容如下所示:
[
{
product_id: 0,
product_name: "my cool product",
product_desc: "desc of my cool product",
price: 10.00,
product_images: [
{
product_image_id: 10,
product_image: "img1.jpg",
},
{
product_image_id: 11,
product_image: "img2.jpg",
},
{
product_image_id: 12,
product_image: "img3.jpg",
}
]
},
{
product_id: 2,
product_name: "my other cool product",
product_desc: "desc of my other cool product",
price: 20.00,
product_images: [
{
product_image_id: 13,
product_image: "img21.jpg",
},
{
product_image_id: 14,
product_image: "img22.jpg",
},
{
product_image_id: 15,
product_image: "img23.jpg",
}
]
},
]
... 等等。
因此很显然, 产品 (父表)和product_images (子表)之间存在父子关系。 不幸的是,我没有成功创建一个API函数,该函数将返回图像数组,该图像数组也具有相关图像数组。 最终目标是我想在一个API调用中一次加载多个产品及其关联的图像,而不是先获得产品,再获得图像。
这是数据库表的快照:
这是我的代码:
将text / json正文发送到此路由。 它接受一个userId和许多要返回的产品:
app.route('/multiplerandomproducts/')
.post(products.get_multiple_random_products);
post body: {user_id: <num>, product_count: <num>}
在我的ProductsController.js控制器中,我具有以下内容:
exports.get_multiple_random_products = function(req,res) {
var postData = new Product(req.body);
Product.getMultipleRandomProducts(postData.data, function(err,products) {
if(err) {
res.send(err);
} else {
res.json(products);
}
});
}
在我的Products.js模型中,我具有以下内容:
// get a random product for the userId
Product.getMultipleRandomProducts = function getMultipleRandomProducts(postData, result) {
var userId = postData.user_id;
var productCount = postData.product_count;
var sqlStr = "SELECT DISTINCT a.* FROM product a "
+ " INNER JOIN product_category b ON b.product_id = a.product_id "
+ " INNER JOIN user_category c ON c.category_id = b.category_id "
+ " WHERE c.user_id= ? "
// get only products that the user hasn"t seen before
if(process.env.APP_HIDESEENPRODS === "1") {
sqlStr += " AND a.product_id NOT IN (SELECT c.product_id from seen_product c WHERE c.user_id = ?)";
}
sqlStr += " ORDER BY RAND() LIMIT ?";
sql.query(sqlStr, [userId, userId, productCount], function(err, res) {
if(err) {
result(err, null);
} else {
// hide from the use if this flag is set in the app
if(!process.env.APP_HIDESEENPRODS === "1") {
insertUserSeenProduct(userId, res[0].product_id);
}
result(null,res);
}
});
}
我还有一个ProductImages.js模型,该模型作为获取特定产品的图像的方法,如下所示:
ProductImage.getAllProductImages = function getAllProductImages(productId, result) {
sql.query("Select * from product_image WHERE product_id = ? ", productId, function (err, res) {
if(err) {
console.log("error: ", err);
result(null, err);
}
else {
result(null, res);
}
});
};
这是我尝试实现的函数版本。 当我指示我想要三个记录时,我得到一个具有三个空值的对象,即[null,null,null]。 我想我很亲密,只是看不到我在做错什么...。
Product.getMultipleRandomProducts = function getMultipleRandomProducts(postData, result) {
var userId = postData.user_id;
var productCount = postData.product_count;
var sqlStr = "SELECT DISTINCT a.* FROM product a "
+ " INNER JOIN product_category b ON b.product_id = a.product_id "
+ " INNER JOIN user_category c ON c.category_id = b.category_id "
+ " WHERE c.user_id= ? "
// get only products that the user hasn"t seen before
if(process.env.APP_HIDESEENPRODS === "1") {
sqlStr += " AND a.product_id NOT IN (SELECT c.product_id from seen_product c WHERE c.user_id = ?)";
}
sqlStr += " ORDER BY RAND() LIMIT ?";
sql.query(sqlStr, [userId, userId, productCount], function(err, res) {
if(err) {
result(err, null);
} else {
// hide from the use if this flag is set in the app
if(!process.env.APP_HIDESEENPRODS === "1") {
insertUserSeenProduct(userId, res[0].product_id);
}
result(null, res.map((item) => {
sql.query("Select * from product_image WHERE product_id = ? ", item.product_id, function (err, res2) {
if(err) {
console.log("error: ", err);
result(null, err);
}
else {
item.product_images = res2;
}
});
}));
}
});
}
因此,我尝试简单地遍历返回的产品数组并返回产品图像,如果这不是异步的,则可以很好地工作。 但是,当我尝试此操作时,我返回了一个带有三个产品的对象(如果我要三个),但是只有一个(第一个)产品为其分配了图像。
总而言之,我想返回一个看起来像这样的对象:
那么,有人可以请告诉我我该怎么做? 我仍然在努力围绕回调函数,而我将要患有脑动脉瘤!
因为每种产品的图像都是单独获取的,所以预期的结果就是您现在所获得的。 实际上,如果您使用服务器(不是本地服务器),则没有图像返回到任何产品的机会。
使用async/await
并promisify
您的函数获取生产映像:
sql.query(sqlStr, [userId, userId, productCount], async function(err, res) {
if(err) {
result(err, null);
} else {
// hide from the use if this flag is set in the app
if(!process.env.APP_HIDESEENPRODS === "1") {
insertUserSeenProduct(userId, res[0].product_id);
}
// Get the list of images thru promisify
const getImages = function(item) {
return new Promise( function(resolve, reject) {
sql.query("Select * from product_image WHERE product_id = ? ", item.product_id, function (err, res2) {
if(err) {
console.log("error: ", err);
reject(result(null, err));
}
else {
item.product_images = res2;
resolve(item);
}
});
});
};
let products = [];
const returnFalse = () => false;
for (let i = 0; i < res.length; i++ ) {
let product = await getImages(res[i]).catch(returnFalse);
if (product) {
products.push(product);
}
}
result( null, products);
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.