【问题标题】:waiting for json response in angularjs factory在angularjs工厂等待json响应
【发布时间】:2015-10-10 00:52:33
【问题描述】:

我越来越接近寻求 JSON 响应。在此示例中, events 变量在返回后被填充,导致空白输出。我需要它等待。我已经读过一个承诺是要走的路......但不确定它是如何工作的......在我的console.log中你可以看到数组但是Events.all();返回 null。

    .factory('Events', function($http) {
         var events="";
          $http.get('http://appserver.falconinet.com/events.lasso').then(function(resp) {
            events = resp.data;
              console.log(events);
          }, function(err) {
            console.error('ERR', err);
            // err.status will contain the status code
          })
              return {
                all: function() {
                  return events;
                },
                get: function(eventId) {
                  for (var i = 0; i < events.length; i++) {
                    if (events[i].id === parseInt(eventId)) {
                      return events[i];
                    }
                  }
                  return null;
                }
              }

        })

这是我的控制器:

    // events

    .controller('EventsCtrl', function($scope, Events) {
        $scope.events = Events.all();
    })

    .controller('EventDetailCtrl', function($scope, $stateParams, Events) {
      $scope.event = Events.get($stateParams.eventId);
    })

【问题讨论】:

  • 您的端点是否有能力在发送 id 时返回单个事件?还是您将所有内容存储在一个文件中?
  • 它只是来自服务器的一个响应。我可以让服务器做任何我想做的事情,但是如果我对事件变量进行硬编码,这会起作用,但由于 http.get 是异步的,它会在后台触发,并且在调用 Events.all 之前不会完成。这是一个移动离子应用程序。

标签: json angularjs asynchronous


【解决方案1】:

Following 将返回由$http 创建的promise 并缓存所有事件的加载。

.factory('Events', function ($http, $q) {
   function loadEvents(id) {
       var promise = $http.get('http://appserver.falconinet.com/events.lasso', {cache: true});
       // return the promise 
       return promise.then(function (resp) {
           var events = resp.data;
           if (id) {
               // returns item or promise rejection
               return getEventById(id, events);
           } else {
               return events;
           }
       }).catch (function (err) {
           console.log('Events error ', err);
       });
   }

   // helper function , returns event or  promise rejection
   function getEventById(id, events) {
       for (var i = 0; i < events.length; i++) {
           if (events[i].id === parseInt(eventId)) {
               return events[i];
           }
       }
       return $q.reject('None found');
   }

   return {
       all: function () {
           return loadEvents();
       },
       get: function (eventId) {
          return loadEvents(eventId);
       }
   }

});

然后在控制器中,您需要在 promise then 回调中解析您的数据

.controller('EventsCtrl', function($scope, Events) {
     Events.all().then(function(events){
         $scope.events = events;
     });
})

.controller('EventDetailCtrl', function($scope, $stateParams, Events) {

     Events.get($stateParams.eventId).then(function(event){
         $scope.event = event;
     });
})

【讨论】:

  • 这适用于 /events 选项卡。很棒的工作!然而,点击标签,我得到一个错误:TypeError: Cannot read property 'then' of undefined 我也得到:ReferenceError: eventId is not defined
  • 哎呀,我在get 中遗漏了return ...现在已修复
  • 如果eventId 没有定义需要查看路由配置。应该首先确保它存在于控制器中
  • if (events[i].id === parseInt(eventId)) {更改为if (events[i].id === parseInt(id)) {
  • 如果您希望将该路径添加为书签,那么向 API 发出单个请求也是有意义的......将节省加载所有这些
【解决方案2】:

正如您所提到的,将您的实际流程包装在一个新的承诺中是可行的方法。为了做到这一点,这个工厂的使用需要一些调整。 Lemme 尝试从您的脚本中编写一个示例,但我不保证在第一次尝试时让它工作:)

.factory('Events', function($http, $q) {
  return {
    all: function() {
      var myPromise = $q.defer();

      $http.get('http://appserver.falconinet.com/events.lasso')
      .then(function(resp) {
        myPromise.resolve(resp.data);
      }, function(err) {
        myPromise.reject(err);
      });

      return myPromise.promise;
    },
    get: function(eventId) {
      var myPromise = $q.defer();

      $http.get('http://appserver.falconinet.com/events.lasso')
      .then(function(resp) {
        var events = resp.data;
        for (var i = 0; i < events.length; i++) {
          if (events[i].id === parseInt(eventId)) {
            myPromise.resolve(events[i]);
          }
        }
      }, function(err) {
        myPromise.reject(err);
      });

      return myPromise.promise;
    }
  }
});

除此之外,这可以在您放置时进行改进,但在知道如何处理 Promise 后我发现这样做非常简单。

使用它们会是这样的:

// Get all
Events.all().then(function(events){
  $scope.events = events;
});

// Get one
Events.get(eventId).then(function(event){
  $scope.events = event;
});

【讨论】:

    猜你喜欢
    • 2015-01-09
    • 2015-11-10
    • 1970-01-01
    • 1970-01-01
    • 2016-07-04
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多