#javascript #node.js #asynchronous #sequelize.js
Вопрос:
Проблема
Я пытаюсь вызвать функцию базы данных при отображении массива. Я создал несколько примеров кода, чтобы продемонстрировать свою проблему в меньшем масштабе. Я использую зависимости «mysql2» и «sequelize», а также MySQL Workbench.
Цель в примере кода
У меня в базе данных есть две таблицы — одна называется «ящики», а другая — «предметы». Каждый элемент будет находиться в коробке (у него будет свойство ‘box_id’). У каждой коробки есть свое местоположение. Я хочу получить массив объектов, в котором просто отображается имя элемента и расположение поля, в котором он находится (а не только идентификатор). Я хочу, чтобы это было сделано как можно более чистым способом. Я знаю, что есть способ связать две базы данных вместе, и ответ о том, как это сделать, был бы признателен, но я чувствую, что изучил бы более важные концепции, используя другой метод — поэтому в идеале я хотел бы альтернативное решение.
Код
Функция mainFunction() является отправной точкой
// Gets all items currently in my database and returning the dataValues const getAllItems = async () =gt; { const findAllItems = await Item.findAll() const items = findAllItems.map(item =gt; item.dataValues) return items } // Gets a box from my database, by ID, and returning its dataValues const getOneBox = async (id) =gt; { const findOneBox = await Box.findOne({ where: {id}}) return findOneBox.dataValues } // Starting point const mainFunction = async () =gt; { // Get all items in database const items = await getAllItems() // Go through each item, and everytime, get the box that corresponds to the item's box_id const myArray = items.map(async item =gt; { const getBox = await getOneBox(item.box_id) // Return an object with my custom formatting, and including the box's location return { itemID: item.id, itemName: item.name, itemLocation: getBox.location } }) // The function will only work if I manually give my function enough time to finish console.log('myArray before delay =gt; ', myArray) await new Promise(response =gt; setTimeout(response, 500)) console.log('myArray after delay =gt; ', myArray) }
Вот результат в моем терминале:
Setup
Here is my setup if it matters. I populated my tables manually to simplify things:
// Populating the existing 'test' schema with relevant tables and running main function after connecting const Sequelize = require('sequelize') const database = new Sequelize ('test', 'root', [REDACTED], { host: 'localhost', dialect: 'mysql', define: { timestamps: false } }) const connect = async () =gt; { await database.authenticate() .then(async () =gt; { await database.sync() console.log('Connected...') mainFunction() }).catch(error =gt; { console.log('Failed to connect =gt; ', error) }) } connect() // Defining my models const Box = database.define('box', { name: Sequelize.STRING, location: Sequelize.STRING }) const Item = database.define('item', { name: Sequelize.STRING, box_id: Sequelize.INTEGER })
Ответ №1:
Оказывается, проблема заключалась в моем подходе; на самом деле с циклами for все очень просто. Я оставлю свое решение на случай, если оно кому-нибудь поможет.
Это просто добавляет еще одно свойство в мой массив элементов
const mainFunction = async () =gt; { const items = await getAllItems() for(i = 0; i lt; items.length; i ) { const getBox = await getOneBox(items[i].box_id) items[i]['location'] = getBox.location } console.log(items) }
Это для того, чтобы я мог отформатировать его по-своему
const mainFunction = async () =gt; { const items = await getAllItems() const itemsFormatted = [] for(i = 0; i lt; items.length; i ) { const getBox = await getOneBox(items[i].box_id) itemsFormatted.push({ itemID: items[i].id, itemName: items[i].name, itemLocation: getBox.location }) } console.log(itemsFormatted) }