如何检查对象数组是否为空?

时间:2015-04-27 06:12:34

标签: javascript angularjs

var app = angular.module('app',['ui.bootstrap']);

app.controller("ListCtrl", function ($scope, $http) {

    $scope.submit = function () {
        $scope.loading = true;
        $scope.error = false;
        $http.get('http://www.omdbapi.com/?s=' + $scope.search + '&r=json')
               .then(function (res) {
                    var titles = [];
                    angular.forEach(res.data.Search, function(item){
                       $http.get('http://www.omdbapi.com/?t=' + item.Title + '&y=&plot=full&r=json').then(function(res){
                       if (res.data.Poster === "N/A") {
                         res.data.Poster = "http://placehold.it/350x450/FF6F59/FFFFFF&text=Image+not+Available!!";
                       }
                        titles.push(res.data); 
                      });  
                    });

                   $scope.movie = titles;
                   $scope.results = true;
                   $scope.error = false;
                   $scope.loading = false;


                   if (titles.length==0) {           // not working
                       $scope.results = false;
                       $scope.error = true;
                   }


               })

我尝试了几件事:

Object.getOwnPropertyNames(titles).length === 0) 
obj == null 

它们似乎都不起作用......

4 个答案:

答案 0 :(得分:2)

由于不正确的范围

,这种情况正在发生

var titles = [];.then

中定义

并且您正在检查.then

之外的长度

由于在titles之外.then不可用,因此无效。 (undefined.length==0

解决方案:

.then(function (res) {
                    var titles = [];
                    angular.forEach(res.data.Search, function(item){
                       $http.get('http://www.omdbapi.com/?t=' + item.Title + '&y=&plot=full&r=json').then(function(res){
                       if (res.data.Poster === "N/A") {
                         res.data.Poster = "http://placehold.it/350x450/FF6F59/FFFFFF&text=Image+not+Available!!";
                       }
                        titles.push(res.data); 
                      }); 
               $scope.movie = titles;
               $scope.results = true;
               $scope.error = false;
               $scope.loading = false;


               if (titles.length==0) {           // now this will work
                   $scope.results = false;
                   $scope.error = true;
               }  
    });//titles will not be available after this.

答案 1 :(得分:0)

$http.get()是异步的,因此语句if (titles.length==0) {会立即执行。

有一个计数器来确定所有Promise何时得到解决,然后执行检查。在回调中移动if语句。

 var count = res.data.Search.length;

 angular.forEach(res.data.Search, function(item){
   $http.get('http://www.o....rest of code').then(function(res) {
      // rest of code

      titles.push(res.data); 
      if (!count-- && !titles.length) {
          $scope.results = false;
          $scope.error = true;
        }
      }
    });
 });

答案 2 :(得分:0)

在您的情况下,检查

titles.length 

将在

之前执行
titles.push

因为您使用的是稍后将返回的异步请求。 您需要将语句包装到请求的答案块中。

答案 3 :(得分:0)

除此之外,但对我的实践和未来的帮助有益:

你遇到的部分问题是范围管理(JS范围,而不是Angular $范围),其中一部分是并发管理,其中一部分似乎是简单的旧范围格式化,很难看到所有控制块的开始和结束(当它不仅仅是/ else,而且还有回调/承诺时会变得很糟糕)。

这是一个很小的例子,说明如何通过快速重构问题来解决这些问题:



function pluck (key) {
  return function pluckFrom(obj) { return obj[key]; };
}

angular.module("app", ["ui.bootstrap"]);

angular.moule("app").service("omdbService", ["$http", function ($http) {
  function getSearch (search) {
    var searching = $http.get("http://www.omdbapi.com/?s=" + search + "&r=json")
      .then(pluck("data"));
    return searching;
  }

  function getMovie (title) {
    var searching = $http.get("http://www.omdbapi.com/?t=" + title + "&y=&plot=full&r=json")
      .then(pluck("data"));
    return searching;
  }

  return {
    getSearch: getSearch,
    getMovie: getMovie,
    getPlaceholderPoster: function () { return "http://placehold.it/350x450/FF6F59/FFFFFF&text=Image+not+Available!!"; }
  };
}]);



angular.moule("app").controller("ListCtrl", ["$scope", "$q", "omdbService", function ($scope, $q, omdb) {
  function loadMovie (movie) {
    return omdb.getMovie(movie.Title)["catch"](function () { return undefined; });
  }
  function movieExists (movie) { return !!movie; }
  function updatePoster (movie) {
    movie.Poster = movie.Poster || omdb.getPlaceholderPoster();
    return movie;
  }
  function setResults (movies) {
    $scope.movie = movies; // $scope.movies, instead?
    $scope.results = true;
    $scope.error = false;
    $scope.loading = false;
  }

  function handleError () {
    $scope.results = false;
    $scope.error = true;
  }

  $scope.submit = function () {
    $scope.loading = true;
    $scope.error = false;

    omdb.getSearch($scope.search)
      .then(pluck("Search"))
      .then(function (movies) { return $q.all(movies.map(loadMovie)); })
      .then(function (movies) { return movies.filter(movieExists).map(updatePoster); })
      .then(setResults, handleError);
  };

}]);




有8000种有效的处理方法,每个人都会看到它有点不同 这也不是我在制作中如何处理它,但也不是太远......

将所有端点调用移出到负责这些操作的服务,这意味着系统中的任何控制器(以该模块作为依赖项)都可以访问它们。

为每个函数做一些小事情并让Array.prototype方法进行迭代(IE8可以在需要时进行填充)意味着每个函数都是超级特定的。

通过将控制器/服务功能包装在数组中并命名它们的依赖关系,它们现在已经缩小了。

submit()的正文少于10行,并处理各种疯狂的异步内容,但我知道我已经处理了错误,例如其中一部电影返回404(我的代码应该仍然火,剩下的电影,其他人的代码可能没有 - 如果服务器为电影投掷错误,大多数代码将永远不会触发成功或将在程序中一直失败。 现在,我没有检查服务器是否正在为电影"发送正确类型的数据,但情况有所不同。