I am trying to call a database function while mapping an array. I created some sample code to demonstrate my issue on a smaller scale. I am using the 'mysql2' and 'sequelize' dependencies, as well as MySQL Workbench.
I have two tables in my database - one called 'boxes' and one called 'items'. Each item will be in a box (it will have a property of 'box_id'). Each box has a location. I want to get an array of objects that simply shows the name of the item and the location of the box it's in (not just the ID). I want this to be run in the cleanest way possible. I am aware there's a way to relate the two databases together, and an answer on how to do that would be appreciated, but I feel I would learn more important concepts using a different method - so ideally, I would like an alternative solution.
mainFunction() is the starting point
// Gets all items currently in my database and returning the dataValues
const getAllItems = async () => {
const findAllItems = await Item.findAll()
const items = findAllItems.map(item => item.dataValues)
return items
}
// Gets a box from my database, by ID, and returning its dataValues
const getOneBox = async (id) => {
const findOneBox = await Box.findOne({ where: {id}})
return findOneBox.dataValues
}
// Starting point
const mainFunction = async () => {
// 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 => {
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 => ', myArray)
await new Promise(response => setTimeout(response, 500))
console.log('myArray after delay => ', myArray)
}
Here is the result in my terminal:
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 () => {
await database.authenticate()
.then(async () => {
await database.sync()
console.log('Connected...')
mainFunction()
}).catch(error => {
console.log('Failed to connect => ', 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
})
Turns out the issue was in my approach; it's actually very easy with for loops. I'll leave my solution in case it helps anyone.
This one just adds another property to my items array
const mainFunction = async () => {
const items = await getAllItems()
for(i = 0; i < items.length; i++) {
const getBox = await getOneBox(items[i].box_id)
items[i]['location'] = getBox.location
}
console.log(items)
}
This one is for if I wanted to format it in my own way
const mainFunction = async () => {
const items = await getAllItems()
const itemsFormatted = []
for(i = 0; i < 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)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.