Store the result in a global variable in Aurelia

How to access the returned data from getData() in printData? Can I store the data in a global variable?

The following is what I have as an example:

home.js

export class Home {
    //d;
    constructor() {
        this.printData();
    }
    getData() {
        httpClient.fetch('example.com/api/v')
            .then(response => response.json())
            .then(data => {
                return data;
                //this.d = data;
            });
    }
    printData() {
        var data = this.getData();
        console.log(data.name);
        //console.log(this.d.name);
    }
}
1 Like

The fetch is an asynchronous function and returns a promise, therefore you need to return the resulting promise in getData to access the result in printData. If you store the result in a global variable, the fetch request is not completed before you want to access it.

export class Home {
    constructor() {
        this.printData();
    }

    getData() {
        return httpClient.fetch('example.com/api/v')
            .then(response => response.json())
            .then(data => {
                return data;
            });
    }

    printData() {
        this.getData()
            .then(data => console.log(data.name));
    }
}

Note the return in getData and the using of the then in printData.

3 Likes

Is there a way so the function printData() will return the data? So for example:

<template>
   <div repeat.for="name of names">
    <p>Hello ${printData(name)}!</p>
   </div>
</template>
export class Home {
    constructor() {
        this.printData();
    }

    getData() {
        return httpClient.fetch('example.com/api/v')
            .then(response => response.json())
            .then(data => {
                return data;
            });
    }

    printData() {
        //var name;
        this.getData()
            .then(data => console.log(data.name));
            //return data.name;
            //name = data.name;
    }
    //return name
}
1 Like

http://www.sobell.net/aurelia-async-bindings/ suggests using a custom binding behavior that will put a “loading” message when a promise is returned and later replace the message with what the promise resolves.

Basically if you add this to your resources

export class asyncBindingBehavior {
 
  bind(binding, source, busymessage) {
    binding.originalupdateTarget = binding.updateTarget;
    binding.updateTarget = (a) => { 
      if (typeof a.then === 'function') {
        if (busymessage) 
          binding.originalupdateTarget(busymessage);
        a.then(d => { binding.originalupdateTarget(d); });
      }
      else
        binding.originalupdateTarget(a);
     };
  }
 
  unbind(binding) {
    binding.updateTarget = binding.originalupdateTarget;
    binding.originalupdateTarget = null;
  }
}

Then you can do

<template>
   <div repeat.for="name of names">
    <p>Hello ${printData(name) & async}!</p>
   </div>
</template>
1 Like

With all due respect I would highly recommend to read up about how promises work as that is a fundamental concept of JS unrelated to Aurelia. Here is a nice read https://javascript.info/promise-basics just as an example your printData doesnt return the promise so even if you’d use an async binding it wouldn’t work. Again this is not meant as an insult in any way but its paramount to properly grasp a few basic constructs. I can assure you that doing so will help with every Framework you might use in the future

6 Likes

There is also this ready-made plugin also handling observables https://github.com/zewa666/aurelia-async-binding

4 Likes

Man, who’s that “Austrian guy” that owns so many useful Aurelia plugins?

6 Likes