1

I'm trying to assign a value of an observable to a variable but it returns Undefined.

Is there any way to assign this value to a variable outside the subscribe method?

new Observable((observer) => {
  const reader = new FileReader();
  reader.onload = () => {
    observer.next(reader.result);
    observer.complete();
  };
  reader.onerror = e => observer.error(e);
  reader.readAsDataURL(file);
  return () => {
    if (reader.readyState === 1) {
      reader.abort();
    }
  };
});
let result;
getBase64(blob)
 .subscribe((base64) => { result = base64; });
return result;
user458975
  • 25
  • 7

1 Answers1

1

You may be running into the difference between synchronous and asynchronous programming.

In a nutshell, result is returned immediately, while observer.next is only called once the onload function is executed some time in the future which might be immediately, seconds later, or even never.

So once you try to do something asynchronous, you effectively have to execute the result handler as a different block of code.

If I were wanting to get the result from a FileReader, I'd usually go for a promise approach, (rather than an Observable) as I'm only expecting a single value (or an error). While similar, Promises are a bit simpler, while Observables are more powerful.

A rough example:

function getFileContents(file) {
  return new Promise((resolve, reject) => {
    var reader = new FileReader();
    reader.onload = evt => resolve(evt.target.result);
    reader.onerror = err => reject(err);
    reader.readAsText(file);
  });
}

This function will give you back a Promise<string> (a promise that contains a string). You still need to "unwrap" the promise to get the internal value though (using then or async/await-style programming).

If you are really sure you want an observable, then I'd probably still use the above promise function, but call it like this:

import { from } from 'rxjs'; 

function getFileContents(file) {
  ...
}

const myObservable = from(getFileContents(fileBlob));

Jono Job
  • 2,732
  • 1
  • 23
  • 23
  • Thanks Jono, Promises are the better approach. I declared a value `let result = '';` and then used `then` to unwrap the data like this: `getFileContents(blob).then(base64 => result = base64);` but still when I log my `result` variable in console it shows empty string! – user458975 May 24 '19 at 15:06
  • Yes, it will, because `result` is returned by the function before its value is assigned in the `then` handler. I suggest you add some `console.log` calls in a few places in the function and in the `then` handler to see the order the code runs in. – Jono Job May 27 '19 at 03:07