Question: I am new to Angular and working on a sample app, which accepts a property file as input from html, process the files and stores the values in a map using typescript. I am able to store the value in the map but not able to access the map from another component.

> 
> File-reader-component.ts
> 
> 
> 

```
export class FileReaderComponent {
    static readFileAsMap(file: File): Map<string, string> {
        let map :Map<string, string>= new Map<string, string>();

        let fileReader = new FileReader();
        fileReader.onloadend = (e) => {
            // By lines
            let lines = fileReader.result.toString().split('\n');
            for(let line = 0; line < lines.length; line++){
                if(lines[line].startsWith('#') || 
                    lines[line].startsWith('//') ||
                    ! lines[line].includes('=') ) {
                    // invalid line - ignoring it
                    continue;
                }
                let lineArr = lines[line].split('=');
                let key = lineArr[0].trim();
                let value = lineArr[1].trim();

                map.set(key, value);
                // not checking duplicate keys to let override the config
            }
        };

        fileReader.readAsText(file);
        console.log(map);
        return map;
    }
}

```

In the above file, console.log(map) works fine. But when we call this method in another component(as below) it returns map with 0 elements.

```
let config: Map<string, string> = FileReaderComponent.readFileAsMap(configFile);

```

Answer: 
Well first of all, the reason it returns map with 0 elements is because onloadend is called asynchronously. readAsText is itself an asynchronous thing, and when it's done it will call onloadend. There's no real guarantee (in fact it's almost certain not to happen) that it will call it before the return gets executed. 

You need to handle this asynchronicity, say via a promise.

Now for the puzzler which is that console.log is non trivial, well that's the browser playing a bit of a trick on you. It console.logs a reference, by the time you look at that reference in the terminal, it has been populated, and the browser 'helpfully' shows it as populated. 

To see what I mean, paste this into your terminal

```
function f() { 
    const x = {}; 
    console.log(x); 
    setTimeout(() => {x[1] = 2}) 
}

```

and invoke f(), logically you would expect to see {}. But the browser plays its tricks and you see { 1: 2 }
The `map` variable is assigned values asynchronously. You could try to return an observable (using for eg. RxJS [`Subject`](https://rxjs-dev.firebaseapp.com/guide/subject)) from the function. Try the following

```js
static readFileAsMap(file: File): Observable<Map<string, string>> {
  const result = new Subject<Map<string, string>>();

  let fileReader = new FileReader();
  fileReader.onloadend = (e) => {
      // By lines
      let map: Map<string, string> = new Map<string, string>();
      let lines = fileReader.result.toString().split('\n');
      for(let line = 0; line < lines.length; line++){
          if(lines[line].startsWith('#') || 
              lines[line].startsWith('//') ||
              ! lines[line].includes('=') ) {
              // invalid line - ignoring it
              continue;
          }
          let lineArr = lines[line].split('=');
          let key = lineArr[0].trim();
          let value = lineArr[1].trim();

          map.set(key, value);
          // not checking duplicate keys to let override the config
      }
      result.next(map);          // <-- push value here
  };

  fileReader.readAsText(file);
  console.log(map);
  return result.asObservable();  // <-- return an observable
}

```

Now you need to subscribe to the function `readFileAsMap()` to obtain the values.

```js
let config: Map<string, string>;

FileReaderComponent.readFileAsMap(configFile).subscribe(
  value => { config = value; }
);

```