Search code examples
javascriptes6-promise

JS - Filtering Promise object


Iv'e been trying to filter data (sampleProducts) that i got from firebase. The problem is that sampleProducts data is defined as Promise object since i used then() method to extract it like this:

import fire from "./config/FBConfig"

var sampleProducts = fire.firestore().collection("sampleProducts").doc("dogvrgMGe2rBJkCy7tIw").get().then((doc) => {
        return Object.values(doc.data());  
});

I try to filter the data like this:

import { sampleProducts } from './Data'

class Api {
    usePriceFilter = usePriceFilter === 'true' && true
        return new Promise((resolve) => {
            setTimeout(() => {

                let data = sampleProducts.filter(item => {
                    if (
                        usePriceFilter &&
            (item.price < minPrice || item.price > maxPrice)
                    ) {
                        return false
                    }

                    if (category === 'home') {
                        return true
                    }

                    if (category !== 'All categories' && category !== item.category)
                        return false

                    if (term && !item.name.toLowerCase().includes(term.toLowerCase()))
                        return false

                    return true
                })

                let totalLength = data.length
                data = this.sortByPrice(data, sortValue)
                data = data.slice((page - 1) * itemsPerPage, page * itemsPerPage)
                resolve({ data, totalLength })
            }, 500)
        })
    }
}

So since sampleProducts is Promise i cant filter it, this is the error and the data in console: error + data

Will be happy for any help or suggestions. thanks.


Solution

  • You need to first resolve the promise before you can perform a filter on it.

    If you only need a single item, consider using find instead of filter.

    When sorting, consider following more of a functional style of programming. I've updated the example to show how to use Array.sort function to achieve this.

    function getSampleProducts() {
      return Promise.resolve([
        {id: 1, price: 2},
        {id: 2, price: 3},
        {id: 3, price: 1},
      ]);
    }
    
    const sampleProducts = getSampleProducts();
    
    function getItemUsingID(id) {
      return sampleProducts
        .then(products => {
          return products.find(x => x.id === parseInt(id, 12))
        });      
    }
    
    function getProductsSortedByPrice(page, pageSize) {
      return sampleProducts
        .then(products => {
          return products
            .filter(p => true /* filter logic here */)
            .sort(propertySorter(p => p.price))
            .slice((page - 1) * pageSize, page * pageSize);
        });
    }
    
    function propertySorter(selector) {
      return (a, b) => {
        const valA = selector(a);
        const valB = selector(b);
    
        if (valA > valB) {
          return 1;
        }
        if (valA < valB) {
          return -1;
        }
        return 0;
      }
    }
    
    getItemUsingID('1')
      .then(result => console.log('getItemUsingID', result))
      
    getProductsSortedByPrice(1, 2)
      .then(result => console.log('getProductsSortedByPrice', result))