如何制作' Loading'发生错误时消息是否消失?

时间:2015-09-18 13:24:36

标签: javascript angularjs

当用户点击'搜索'按钮,'正在加载'消息显示,并且当结果显示在屏幕上时消失。

如果地理位置失败,则会向他们显示提醒,但是“加载”#39;消息留在屏幕上。显然,我希望加载消息在地理定位失败时消失。

我知道我必须用代码做一些事情,但我真的不知道从哪里开始。我认为这只是在控制器中添加.finally函数的情况,但这并不起作用。

地理定位工厂:

beerStalker.factory('GeoLocation', function() {
  return {
    getLocation: function() {

      var deferred = $.Deferred();

      // if geo location is supported
      if(navigator.geolocation) {

        // get current position and pass the results to getPostalCode or time out after 5 seconds if it fails
        navigator.geolocation.getCurrentPosition(deferred.resolve, this.geoLocationError, {
          timeout: 5000
        });

      } else {
        alert('Your browser does not support Geo Location.');
      }
      return deferred.promise();
    },

    geoLocationError: function() {
      alert('Geo Location failed.');
    }
  }
});

控制器:

beerStalker.controller('BeerStalkController', ['$scope', '$resource', 'ApiCall', 'GeoLocation', function($scope, $resource, ApiCall, GeoLocation) {

  $scope.autoSearch = function() {
    $scope.loading = true;
    $.when(GeoLocation.getLocation()).then(function(data, textStatus, jqXHR) {
      return [data.coords.longitude, data.coords.latitude];
    }).then(function(location) {
      ApiCall.autoSearch(location[1], location[0]).then(function(results){
        $scope.searchResult = results
        $scope.loading = false;
      });
    }); 
  };

  $scope.customSearch = function() { 
    $scope.loading = true;
    ApiCall.customSearch($scope.cityName).then(function(results){
      $scope.searchResult = results
      $scope.loading = false;
    });
  };
}]);

PS它是用Angular构建的。 Github回购:https://github.com/Yorkshireman/beerstalker

3 个答案:

答案 0 :(得分:0)

我认为这里的主要问题是你不应该在你的GeoLocation工厂中使用deferred.reject,当你应该使用navigator.geolocation时:

} else {
    //alert('Your browser does not support Geo Location.');
    deferred.reject(response);
  }

在此之后,您可以在控制器中轻松添加简单的.catch语句。此catch语句将提交警报,然后您还可以将加载设置为false,如下所示:

.then(function(location) {
  ApiCall.autoSearch(location[1], location[0]).then(function(results){
    $scope.searchResult = results
    $scope.loading = false;
  })
.catch(function(location){
    alert('Your browser does not support Geo Location.');
    $scope.loading = false;
});

希望这有助于回答您的问题。

答案 1 :(得分:0)

你的承诺未解决。你需要拒绝承诺,因为它失败了。像这样。

beerStalker.factory('GeoLocation', function() {
  return {
    getLocation: function() {

      var deferred = $.Deferred();

      // if geo location is supported
      if(navigator.geolocation) {

        // get current position and pass the results to getPostalCode or time out after 5 seconds if it fails
        navigator.geolocation.getCurrentPosition(deferred.resolve, this.geoLocationError, {
          timeout: 5000
        });

      } else {
        deffered.reject('Your browser does not support Geo Location.');
      }
      return deferred.promise();
    },

    geoLocationError: function() {
      alert('Geo Location failed.');
    }
  }
});

在承诺中,需要在then()中提供第二次失败回调。 then(function(success){}, function(failure){})

beerStalker.controller('BeerStalkController', ['$scope', '$resource', 'ApiCall', 'GeoLocation', function($scope, $resource, ApiCall, GeoLocation) {

  $scope.autoSearch = function() {
    $scope.loading = true;
    $.when(GeoLocation.getLocation()).then(function(data, textStatus, jqXHR) {
      return [data.coords.longitude, data.coords.latitude];
    }, function(failureReason){alert(failureReason);}).then(function(location) {
      ApiCall.autoSearch(location[1], location[0]).then(function(results){
        $scope.searchResult = results
        $scope.loading = false;
      });
    }).finally(function(){$scope.loading = false}); 
  };

  $scope.customSearch = function() { 
    $scope.loading = true;
    ApiCall.customSearch($scope.cityName).then(function(results){
      $scope.searchResult = results
      $scope.loading = false;
    });
  };
}]);

请注意,我已将警报移至故障中。我将$scope.loading=false;移动到finally语句,以确保每次都执行它。

答案 2 :(得分:0)

如果您希望resolve数据块生效,则需要rejectfinally。如$q.deferred is an anti-pattern,请改用$q constructor - $q(resolve, reject)

beerStalker.factory('GeoLocation', function () {
    return {
        getLocation : function () {
            return $(resolve, reject) {
                // if geo location is supported
                if (navigator.geolocation) {

                    // get current position and pass the results to getPostalCode or time out after 5 seconds if it fails
                    navigator.geolocation.getCurrentPosition(resolve, reject, { // if it fails 'reject' will be called
                        timeout : 5000
                    });

                } else {
                    alert('Your browser does not support Geo Location.');
                    reject();
                }
            }
        },

        /** notify about the error in the controller
        geoLocationError : function () {
        alert('Geo Location failed.');
        }
         **/

    }
});

/** the GeoLocation.getLocation call in the controller **/
GeoLocation.getLocation().then(function (data, textStatus, jqXHR) { // you don't need when because it's an angular $q promise
    return [data.coords.longitude, data.coords.latitude];
}).then(function (location) {
    return ApiCall.autoSearch(location[1], location[0]);
}).then(function (results) {
    $scope.searchResult = results;
}).catch(function (error) { // catch error and show alert
    alert('Geo Location failed.');
}).finally (function () { // remove loader
    $scope.loading = false;
});