-1

I have a promise that resolves a variable this.data in a Read Excel Service as shown below,

  parseExcel(excelFile): Promise<any>
  {
    /* wire up file reader */
    const target: DataTransfer = <DataTransfer>(excelFile.target);
    if (target.files.length !== 1) throw new Error('Cannot use multiple files');
    const reader: FileReader = new FileReader();
    return new Promise((resolve, reject) => {
        reader.onload = (e: any) => 
        {
          /* read workbook */
          const bstr: string = e.target.result;
          const wb: XLSX.WorkBook = XLSX.read(bstr, { type: 'binary' });

          /* grab first sheet */
          const wsname: string = wb.SheetNames[0];
          const ws: XLSX.WorkSheet = wb.Sheets[wsname];

          /* save data */
          this.data = <AOA>(XLSX.utils.sheet_to_json(ws, { header: 1 }));
          console.log("BOM PARSE SERVICE LOG: " , this.data)
          resolve(this.data);
        };
        reader.readAsBinaryString(target.files[0]);
    })
}

I am now trying to access the resolved array here

async ReadExcel(event)
  {
    return new Promise<Object>((resolve, reject) =>
    {
      var excelContents = this.parser.parseExcel(event).then(function(value)
      {
        return value
      }
      console.log("New Quote Component Log: ", excelContents)
      //need var excelContents to only contain the array and not contain the value of the promise object
    }
  )}
}

the log statement in the latter function brings me back this...

log statement

Is there a way that I can have the variable excelContents only take on the value of the array rather than the entire value of the promise?

Banani720
  • 159
  • 3
  • 17
  • 1
    Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Jared Smith Feb 14 '20 at 20:45

2 Answers2

1

The problem in the ReadExcel function is that .then() always returns the Promise instance, not the actual resolve value. So by doing let blabla = promise.then(v => {return v}), blabla variable will be the promise and to access the resolve value you'll have to do blabla.then(v => ...).

That's why when you console.log the excelContents variable, you see an object with two properties, state, representing the state of the promise, and value, wich is the resolve value.

I recommend, if you are using an async function as I see you do, to use async/await like this:

async ReadExcel(event)
  {
    return new Promise<Object>(async(resolve, reject) =>
    {
      try {
          var excelContents = await this.parser.parseExcel(event)
          console.log("New Quote Component Log: ", excelContents)
          //need var excelContents to only contain the array and not contain the value of the promise object
          resolve(excelContents)
      } catch(e) {
         reject(e)
      }
    }
  )}
}

as await promiseReturningFunc() will return the resolve value.

Be careful of error handling, always use try/catch.

Also please notice that I added async to the promise handler.

0

Whatever you do, you will need to so something asynchronous to get the real, promised data. There is obviously no hope in getting it synchronously.

Your attempt with yet another new promise is not helping you to get any closer (in fact, it employs the promise constructor antipattern). Just do:

async ReadExcel(event) {
    var excelContents = await this.parser.parseExcel(event);
    console.log("New Quote Component Log: ", excelContents);
}

To be clear: don't be tricked into thinking that returning excelContents in this latter function is going to give you synchronous access to it. That would not bring you any benefit, because you will need to await that returned value again, in yet another async function. So... this is it. Do everything you need to do with excelContents, right there, in that async function, after await.

trincot
  • 317,000
  • 35
  • 244
  • 286