Sagi Mann
Sagi Mann

Reputation: 3610

AngularJS: how to load promise into template?

vm.promises = {};

vm.addPromise = function (src) {
  if (!angular.isDefined(vm.promises[src])) {
    vm.promises[src] = $http.get(src).then(function (res) {
      console.log("returning data: " + res.data);
      return res.data;
    });
    console.log("created new promise");
  } else {
    console.log("using existing promise");
  }
  return vm.promises[src];
};

$scope.loadStuff = function (src) {
  console.log("loadStuff " + src);
  return;
  vm.addPromise(src);
};

// ----------------------------------- template:

<body ng-controller="MainCtrl">
  {{loadStuff('stuff.txt')}}
</body>

Hi, I'm trying to http-load a simple promise into my template (using Angular 1.3) but there are 2 problems:

  1. The loadStuff function gets called multiple times (6 on my chrome, inside plunkr)
  2. Even if I reuse the same promise for multiple load-calls, the output is "{}" for some reason although I can see in the log that the data itself was fetched correctly

Note: I cannot use ng-include in my case.

Here's the plunkr, check out the console log to see what I mean...

Expected output: some stuff loaded

Actual output:

{}

How do I get this thing to work?

Upvotes: 1

Views: 1842

Answers (1)

Yaron Schwimmer
Yaron Schwimmer

Reputation: 5357

There are several things that you are doing wrong:

  1. When you assign a promise to a variable like you did in vm.promises[src] = $http.get(src).then(..., then that variable is a promise. It does not get populated with what the callback function returns. The correct approach in this case would be something like:

    $http.get(src).then(function(res) {
      console.log("returning data: " + res.data);
      vm.promises[src] = res.data;
    });
    

    This, by it self will give you your desired result (see here), but if you open developer tools you'll see terrible things: stuff.txt is called loaded multiple times, and eventually angular throws an infinite digest loop error. This is because you call loadStuff from the template. See @Gustav's comment above. Which leads us to...

  2. You shouldn't mix synchronous calls with async calls. You call loadStuff and expect it to behave like a synchronous function and return a value right away, while its implementation is calling an asynchronous function. The correct approach here is to have your controller call the async function once, store the returned value once it resolves, and display the stored value in your template. See a simple example here.

Upvotes: 1

Related Questions