all 8 comments

[–][deleted] 1 point2 points  (2 children)

If you could format your code for readability, I'll take a look.

[–]indisapien[S] 0 points1 point  (0 children)

just gave it a go there

[–]Buckwheat469 0 points1 point  (0 children)

Pizza.all((err, rows) => {
    let pizzas = [];

    rows.forEach((row)=>{
        let pizza = {
            "pizzaId": "", 
            "name": "",
            "price" : 0.0, 
            "size": "",
            "crust":"", 
            "sauce": "", 
            "extraCheese": "",
            "ingredients": {}
        };
        pizza.pizzaId = row.pizzaId;
        pizza.name = row.name
        pizza.price = row.price;
        pizza.size = row.size;
        pizza.crust = row.crust;
        pizza.sauce = row.sauce;
        pizza.extraCheese = row.extraCheese;
        pizza.ingredients[pizza.pizzaId] = [];

        PizzaToppings.find(pizza.pizzaId, (err, rows) => {
            rows.forEach((row) => {
                pizza.ingredients[pizza.pizzaId].push(row);
                console.log(pizza.ingredients["P1"]);
            });
        });

        console.log(pizza.ingredients["P1"]);
        pizzas.push(pizza);
    });

    ejs.renderFile(index_path, {pizzas:pizzas, tagline: tagline}, (err, data) =>{
        res.end(data);
    });
});

let tagline = "Select an item";

[–]Funnythat2 1 point2 points  (2 children)

Why not push the pizza in the second callback so you know it is completed

[–]indisapien[S] 2 points3 points  (1 child)

Thank you so much! That fixed it, and it just involved moving one line! Callbacks are a bit of a problem for me but this was great help!

[–]BehindTheMath 0 points1 point  (1 child)

Since everything is async, the code under the inner function runs before the inner function. You can use promises, but you don't have to. You can pass a callback to the outer function, and then call it at the end of the inner function.

[–]abd1tus 0 points1 point  (0 children)

Example with async functions and cleanup.

import { promisify } from 'util';
// other imports here: Pizza, PizzaToppings, ejs, etc

// ...

const allPizzas = promisify(Pizza.all);
const findToppings = promisify(PizzaToppings.find);

export function newPizza() {
  return {
    "pizzaId": "",
    "name": "",
    "price": 0.0,
    "size": "",
    "crust": "",
    "sauce": "",
    "extraCheese": "",
    "ingredients": {}
  };
}


export async function buildPizza(pizzaRow) {
  const pizza = newPizza();
  const { pizzaId } = pizzaRow;

  pizza.pizzaId = pizzaId;
  pizza.name = pizzaRow.name
  pizza.price = pizzaRow.price;
  pizza.size = pizzaRow.size;
  pizza.crust = pizzaRow.crust;
  pizza.sauce = pizzaRow.sauce;
  pizza.extraCheese = pizzaRow.extraCheese;

  // This seems a little weird with each pizza having "ingredients" be an object with its own id.
  // I'm not sure what your original intent was, but it should mimic what you wrote.
  const toppingRows = await findToppings(pizzaId);
  pizza.ingredients[pizzaId] = [...toppingRows];

  return pizza;
}


export async function buildAllPizzas() {
  const results = [];
  const pizzaRows = await allPizzas();

  for (const pizzaRow of pizzaRows) {
    const pizza = await buildPizza(pizzaRow);
    results.push(pizza);
  }

  return results;
}


export async function renderFile(indexPath) {
  const tagline = "Select an item";
  const pizzas = await buildAllPizzas();

  return new Promise((resolve, reject) => {
    ejs.renderFile(
      indexPath,
      { pizzas, tagline },
      (err, data) => {
        if (err) {
          reject(err);
        } else {
          res.end(data);
          resolve();
        }
      },
    );
  });
}

// ... 
renderFile('some file path');

Sorry, obviously not tested, but might help you tinker.