Loopback3无回调查询及非嵌套获取关联值的可行方法咨询
Hey there! Let's break down your two LoopBack 3 questions clearly— I’ve built several apps with LB3, so I can share practical, tested solutions here.
Absolutely! LoopBack 3 supports Promise-based querying as the official alternative to callback-style code, which is exactly what you’re looking for. Most core model methods (like find(), findById(), create(), etc.) will return a Promise automatically if you don’t pass a callback function. This lets you use then/catch chains or cleaner async/await syntax to avoid callback hell.
Here’s how to fix your example code properly:
Using Promises with then/catch
function getRelatedModel() { // Return the Promise directly instead of trying to assign a synchronous value return relatedModel.find({}) .then(res => { // Do any processing here if needed return res; }) .catch(err => { console.error('Failed to fetch related model:', err); throw err; // Re-throw to let the caller handle the error }); } // Call it like this: getRelatedModel().then(items => { console.log('Fetched items:', items); });
Using async/await (cleaner for sequential code)
async function getRelatedModel() { try { // Await the Promise to get the result directly const items = await relatedModel.find({}); return items; } catch (err) { console.error('Error fetching items:', err); throw err; } } // Call it in another async function: const items = await getRelatedModel();
Note: Your original code’s issue was that the callback runs asynchronously— the function would return undefined before the callback finished. Promises/async/await fix this by properly handling the async flow.
LoopBack 3 returns nested data by default when using include to fetch related models, but you can get flattened results in two practical ways:
Option 1: Fetch nested data then flatten it manually
Use the include option to get the related data, then map the results to a flat structure. This is great if you want to keep using LoopBack’s ORM features.
Example (assuming Order has a customer relation):
async function getOrdersWithFlatCustomerData() { const orders = await Order.find({ include: { relation: 'customer', scope: { fields: ['name', 'email'] // Only fetch the fields you need } } }); // Flatten the nested customer data into top-level fields return orders.map(order => { const orderObj = order.toJSON(); // Convert LoopBack model instance to plain object return { ...orderObj, customerName: orderObj.customer.name, customerEmail: orderObj.customer.email, customer: undefined // Remove the nested customer object if needed }; }); }
Option 2: Use a custom SQL query for direct flat results
If you prefer to skip the ORM’s nested structure entirely, use LoopBack’s query() method to run a JOIN query that returns flat rows directly. This is more efficient for complex joins.
async function getFlatOrdersWithCustomer() { const sql = ` SELECT o.id, o.order_number, o.amount, c.name AS customer_name, c.email AS customer_email FROM Orders o JOIN Customers c ON o.customer_id = c.id `; const flatResults = await Order.query(sql); return flatResults; }
LoopBack doesn’t have a built-in flag to return flat related data directly, but these two approaches work reliably for most use cases.
内容的提问来源于stack exchange,提问作者Mark Ryan Orosa

