nevoni3008
nevoni3008

Reputation: 447

Can't resolve all the promises in Javascript

I'm building a filter function. I have categories and cities, that come like this: ['New York'], ['Cars'], and I'm iterating them to find the products of that category or city. The idea is to put on the products variable the products that come from each city, or category, and then return them to the user.

I fail to return them because when I console log products in the async function it's displaying the products, but although I push thos in the promises array, that array is empty when I call Promise.all.

I know that I need the promises to resolve so I expect to collect them in promises and to await their resolution with Promise.all at the end and convert the data and return all products collected, but the promises array is empty.

import { Product } from "../../models";
import { Response } from "../../utils";

export default async function ProductsFilters(req, res) {
  try {
    const { Cities, Categories } = req.body;

    let products = [];
    let promises = [];

    if (Cities.length > 0) {
      Cities.map(async (city) => {
        const results = await Product.find({ City: city });
        return promises.push(results);
      });
    }

    if (Categories.length > 0) {
      Categories.map(async (category) => {
        const results = await Product.find({ Category: category });
        return promises.push(results);
      });
    }

    const results = await Promise.all(promises);
    results.map((result) => products.push(result));

    if (products.length > 0) Response( res, 200, true, "Të gjitha produktet u morën me sukses.", products);
    else Response(res, 404, false, "Asnjë produkt nuk u gjet në platformë.", null);
  } catch (error) {
    Response( res, 500, false, "Gabim i brendshëm i serverit gjatë gjetjes së produkteve.", null);
  }
}

I'm using Mongo Database and Mongoose to fetch the products, so .find function is returning the products that it matches.

Upvotes: 0

Views: 56

Answers (1)

trincot
trincot

Reputation: 349956

The the map method is synchronous even when you pass it a callback that is asynchronous:

      Cities.map(async (city) => {
        const results = await Product.find({ City: city });
        return promises.push(results);
      });

Those callbacks will return as soon as they encounter await, so the promises array will still be empty when the .map() call returns.

Also map returns an array, which you ignore. Instead you call push inside the map callback. That is bad practice. If you don't expect a returned array, then don't use map, but forEach or for. If you do want to populate an array, then take benefit from the array returned by map.

Here is a rewrite:

async function ProductsFilters(req, res) {
    try {
        const { Cities, Categories } = req.body;
        const products = await Promise.all([
            ...Cities.map(async (City) => Product.find({ City })),
            ...Categories.map(async (Category) => Product.find({ Category }))
        ]);
        if (products.length > 0) {
            Response(res, 200, true, "Të gjitha produktet u morën me sukses.", products);
        } else {
            Response(res, 404, false, "Asnjë produkt nuk u gjet në platformë.", null);
        }
    } catch (error) {
        Response(res, 500, false, "Gabim i brendshëm i serverit gjatë gjetjes së produkteve.", null);
    }
}

Upvotes: 1

Related Questions