Vin Venture
Vin Venture

Reputation: 41

How to return a variable's value which is declared inside of a Promise

Variables declared inside a Promise get returned first and then the function gets executed

I have the following piece of code which first gets some filter values and pushes them into filterFetchPromises. The function of getting the filters in itself is an asynchronous function. Then I process the data inside filterFetchPromises and then I have to return the processed data. The variables used for storing the processed data are declared within the getfilters() function because I need them to set to empty after every iteration.

Currently, when I print out the filter names, filter values, they just show empty. How do I process the data from filterFetchPromises first and then return those values?

function getfilters() {

  return new Promise(function(resolve) {

    let filterFetchPromises = [];
    let dashboardfilters = [];
    let filternames = [];
    let filtervalues = []; 

    filterFetchPromises.push(worksheet.getFiltersAsync());
    Promise.all(filterFetchPromises).then(function (fetchResults) {
      fetchResults.forEach(function (filtersForWorksheet) {
        filtersForWorksheet.forEach(function (filter) {
          dashboardfilters.push(filter);

          if (contains(filternames, filter.fieldName)) {
            console.log("Duplicate Entry")
          }
          else {
            let filtervalues_temp = []
            console.log(filter.fieldName)

            if ((filter.appliedValues).length > 0) {

              filternames.push(filter.fieldName)
              console.log(filter.fieldName)

              filter.appliedValues.forEach(function(test) {
                console.log(test.value)
                filtervalues_temp.push(test.value)
              })

              filtervalues.push(filtervalues_temp)
            }
          }  

        });
      });
    });
    // console.log(filternames)
    // console.log(filtervalues)

    return resolve([filternames, filtervalues]);

  })
}

getfilters().then(function ([filternames, filtervalues]) {
  console.log("Function got over.")
  console.log(filternames)
  console.log(filtervalues)

})

Currently, filter names and filter values are empty. I just want the data to be processed first and then print those variables

Upvotes: 1

Views: 136

Answers (2)

Charlie
Charlie

Reputation: 23798

You should resolve your top level promise with the return value only when your asynchronous operation is complete. In your code, you are doing it before the async operation is complete. Call the resolver right after you populate the arrays.

fetchResults.forEach(function (filtersForWorksheet) {

   ...
   ...

});

resolve([filternames, filtervalues]);

Upvotes: 1

Aayush Sharma
Aayush Sharma

Reputation: 849

You need to keep in mind that Javascript is async and hence your resolve([filternames, filtervalues]); will be called before their values get updated in promise.all.

As per MDN's definition of Promise, the data with which you call the resolve function is the data this promise gets resolved to and hence there is no need to return something.

Move the resolve call inside your promis.all after your filternames and filtervalues get updated.

Try the following code:

function getfilters() {

  return new Promise(function(resolve) {

    let filterFetchPromises = [];
    let dashboardfilters = [];
    let filternames = [];
    let filtervalues = []; 

    filterFetchPromises.push(worksheet.getFiltersAsync());
    Promise.all(filterFetchPromises).then(function (fetchResults) {
      fetchResults.forEach(function (filtersForWorksheet) {
        filtersForWorksheet.forEach(function (filter) {
          dashboardfilters.push(filter);

          if (contains(filternames, filter.fieldName)) {
            console.log("Duplicate Entry")
          }
          else {
            let filtervalues_temp = []
            console.log(filter.fieldName)

            if ((filter.appliedValues).length > 0) {

              filternames.push(filter.fieldName)
              console.log(filter.fieldName)

              filter.appliedValues.forEach(function(test) {
                console.log(test.value)
                filtervalues_temp.push(test.value)
              })

              filtervalues.push(filtervalues_temp)
            }
          }  

        });
        resolve([filternames, filtervalues]);
      });
    });
    // console.log(filternames)
    // console.log(filtervalues)

  })
}

getfilters().then(function ([filternames, filtervalues]) {
  console.log("Function got over.")
  console.log(filternames)
  console.log(filtervalues)

})

Upvotes: 1

Related Questions