简体   繁体   中英

Asynchronous API Request by Angularjs

I have two files foo.js and foo.html.

In foo.js i take information from a API (i suppose its asynchronous) and foo.html has access to that object.

  <tr data-ng-repeat="y in vm.apidata">
                                    <td>{{y.name}}</td>
                                    <td>{{y.is_closed}}</td>
                                </tr>

But here i can't see anything. There is no mistake with codes to show that and i take information as array of objects.

I take information from API properly but vm.apidata is not initialized so that i can show it in foo.html.

How can i ensure that it has been shown?

这听起来像是$ apply()和/或$ watch的工作-一个示例线程可能是这个AngularJS $ location.path(path)最初没有更新

@Aqsan, I'll write this up in an answer as it'll be too verbose for the comments.

My hypothesis is that you have to call $scope.$digest/$apply() upon your external code completing its task or perhaps as soon as the scope object of interests, vm.apidata, is mutated.

IMPORTANT: Angular is expecting vm.apidata to be an scope object. Simply putting in the global window/self scope is not what your markup is referencing.

window.vm.apidata != scope.vm.apidata

If indeed you are correctly updating the scope node, you can use the same scope reference to call scope.$apply().

However if you aren't below is some info. Read more about Scopes .

You can inject references to the $rootScope , which is the top level root scope in your services (provider, factory), controllers and directives . Similarly $scope of hierarchical interest is relevant in controllers and directives and can be injected there thus Scope objects are inherited (cascade down) in a parent-child hierarchy with the exception of isolated scopes which can be implemented in custom directives or in the case of ng-repeat directive for example. I'm going to give you a skeleton for a Controller (for simplicity sake) implementation where you might put implement the connection:

var myModule = angular.module('myModule', []);

// This is a Service
// observe how you inject the root scope
// the array wrapper around the factory is for JS code minification protection which might name your parameter to something shorter and make it invalid (AngularJS-wise)
myModule.factory('retrieveService', ['$rootScope', '$q', function($rootScope, $q) {
  function retrieve(){

    // perhaps return a promise using the injected (light-weight) angular $q service
    var deferred = $q.defer();

    // Your external code can go in here for retrieval
    // When your async code complete call for success
    deferred.resolve(<yourapidata>);

    // alternatively for error
    deferred.reject(<yourerror>);

    // of course you could also just set the value to the $rootScope.vm.apidata here and call $apply
    $rootScope.vm.apidata = <yourapidata>;
    $rootScope.$apply();


    return deferred.promise;

  }
  return retrieve;
  }]);

// This is a Controller
myModule.controller('MyCtrl', ['$rootScope', '$scope', 'retrieveService', '$q', function(rootScope, $scope, retrieveSvc, $q) {

  function retrieve(){
    // Your external code could go in here inside the controller too
    // upon async retrieval perhaps...
    $scope.vm.apidata = <yourvalue>
  }
  // given you take care of your async call using promises and/or callbacks
  retrieveService().then(function(apidata) {
    $scope.vm.apidata = apidata;
    // though $scope is recommended imho, alternatively
    // you could bind the vm.apidata to $rootScope (here or in your service) as well which $scope will inherit
    $rootScope.vm.apidata = apidata;
  });

}])

There is much to learn/expand on and the permutations are vast, but hopefully this gives you a good general direction. $http angular service might be a good option depending on your backend api.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM