简体   繁体   中英

Including the results of an async function in my 'return' while mapping an array

Problem

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.

Goal in Sample Code

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.

Code

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:

在此处输入图片说明

Setup

Here is my setup if it matters. I populated my tables manually to simplify things:

items => 物品

boxes => 盒子

// 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM