2013-06-07 44 views
13

Tôi đang cố gắng sử dụng resolve trong một $routeProvider để hiển thị tuyến đường mới chỉ khi yêu cầu $http hoàn tất. Nếu yêu cầu thành công, lời hứa xuất phát từ $ http.post() được giải quyết và khung nhìn được hiển thị. Nhưng nếu yêu cầu không thành công (hết thời gian chờ hoặc lỗi nội bộ cho ví dụ.), Lời hứa sẽ không bao giờ được giải quyết và chế độ xem sẽ không bao giờ được hiển thị. Làm cách nào tôi có thể xử lý yêu cầu không thành công bằng cách sử dụng resolve?

Các bộ phận quan trọng nhất của mã này là dưới đây:

app.js

$routeProvider.when('/warrantyResult', { 
    templateUrl : 'partials/warranty-result.html', 
    controller : 'WarrantyResultCtrl', 
    resolve : { 
     response : [ 'Warranty', function(Warranty) { 
      return Warranty.sendRequest(); 
     } ] 
    } 
}); 

controllers.js

angular.module('adocDemo.controllers', []).controller('HomeCtrl', [ '$scope', function($scope) { 

} ]).controller('WarrantyCtrl', [ '$scope', '$http', '$location', 'Warranty', function($scope, $http, $location, Warranty) { 
    $scope.submitWarranty = function() { 
     $scope.loading = true; 
     Warranty.setRequestData($scope.data); 
     $location.path('/warrantyResult'); 
    }; 
} ]).controller('WarrantyResultCtrl', [ '$scope', 'Warranty', function($scope, Warranty) { 

    $scope.request = Warranty.getRequestData(); 
    $scope.response = Warranty.getResponseData(); 
} ]); 

services.js

angular.module('adocDemo.services', []).factory('Warranty', [ '$http', '$timeout', function($http, $timeout) { 
    /** 
    * This service is used to query the Warranty Webmethod. The sendRequest 
    * method is automaticcaly called when the user is redirected to 
    * /warrantyResult route. 
    */ 
    var isDataSet = false; 
    var requestData = undefined; 
    var responseData = undefined; 
    return { 
     setRequestData : function(data) { 
      //Setting the data 
      isDataSet = true; 
     }, 
     getRequestData : function() { 
      return requestData; 
     }, 
     sendRequest : function(data) { 
      if(isDataSet) { 
       var request = $http.post('url/to/webservice', requestData); 
       request.success(function(data) { 
        responseData = data; 
       }); 
       return request; 
      } 
     }, 
     getResponseData : function() { 
      return responseData; 
     } 
    }; 
} ]); 

tôi biết tôi có thể sử dụng lời hứa vòng cuộc gọi $ http và giải quyết nó ngay cả khi yêu cầu là một thất bại, nhưng tôi tự hỏi nếu có một giải pháp đơn giản hơn.

Cảm ơn bạn đã đọc và, hy vọng, giúp đỡ :)

+0

Tùy thuộc vào cách bạn muốn ứng dụng của mình hoạt động khi giải quyết không thành công? – Stewie

+0

Hành vi tốt nhất sẽ là chuyển hướng người dùng đến một tuyến đường khác (/ requestError?) Khi giải quyết không thành công. Hoặc/warrantyResult có thể được hiển thị và bộ điều khiển của tuyến đường này sẽ chịu trách nhiệm kiểm tra xem yêu cầu có thành công hay không. – pdegand59

Trả lời

0

Sau khi tìm kiếm sâu, tôi không thể tìm thấy giải pháp cho vấn đề này.

Tôi đã quyết định thả stat giải quyết trong định nghĩa tuyến đường của mình và tôi sử dụng đoạn mã sau trong Mã bảo hành.

$scope.submitWarranty = function() { 
    $scope.formatUserData(); 
    if ($scope.verifyUserData()) { 
     $scope.loading = true; 
     Warranty.setRequestData($scope.data); 
     Warranty.sendRequest().success(function() { 
      $location.path('/warrantyResult'); 
     }).error(function() { 
      $location.path('/webserviceError'); 
     }); 
    } 
}; 

Không phải rất thông minh, nhưng hoạt động như intented ... Nếu ai đó vẫn còn có những giải pháp cho vấn đề ban đầu, tôi sẽ rất vui mừng khi đọc nó!

+0

Điều gì về chỉ có '$ location.path ('/ webserviceError')' và làm điều đó trong trình xử lý lỗi của cuộc gọi '$ http'. Vì vậy, bạn có thể có tuyến đường giải quyết và bạn không cần phải suy nghĩ về lời hứa bị từ chối bởi vì nó sẽ được xử lý trong dịch vụ –

8

Tôi nghĩ rằng cách duy nhất để làm điều đó từ resolve là để tự giải quyết lời hứa trả về bởi Warranty.sendRequest và rewrap nó trong một lời hứa mới:

resolve : { 
    response : [ 'Warranty' '$q', function(Warranty, $q) { 
    var dfd = $q.defer(); 

    Warranty.sendRequest().then(function(result) { 
     dfd.resolve({ success: true, result : result }); 
    }, function(error) { 
     dfd.resolve({ success : false, reason : error }); 
    }); 

    return dfd.promise; 

    } ] 
} 

Trong WarrantyResultCtrl, bạn có thể kiểm tra nếu một lỗi xảy ra và tạo ra một chuyển hướng.

EDIT: giải pháp sạch hơn nhiều:

// WarrantyCtrl 
$scope.$on('$routeChangeError', function() { 
    // handle the error 
}); 
$scope.submitWarranty = function() { 
    $scope.loading = true; 
    Warranty.setRequestData($scope.data); 
    $location.path('/warrantyResult'); 
}; 

(plunker demo)

+0

plunker của bạn không hoạt động. Nhưng thx anyways cho câu trả lời của bạn! Im sẽ đưa ra một shot tại giải pháp của bạn. – pdegand59

+0

@ pdegand59, xin lỗi! Tôi đã làm sạch một chút quá nhiều ngày hôm qua rõ ràng :( – robertklep

3

Những gì tôi đã tìm thấy là bộ điều khiển không bị sa thải ở tất cả nếu Promiserejected, và tầm nhìn của bạn không bao giờ được trả lại - giống như bạn.

Những gì tôi cũng phát hiện ra là nếu bạn xử lý các Promise với một .then() trong $routeProvider 's resolve của bạn, .then() sẽ trả về một mới Promise đó là resolved và điều khiển của bạn là bắn sau khi tất cả, mặc dù không có dữ liệu bạn đang mong đợi .

Ví dụ:

$routeProvider.when('/warrantyResult', { 
    templateUrl : 'partials/warranty-result.html', 
    controller : 'WarrantyResultCtrl', 
    resolve : { 
     response : [ 'Warranty', function(Warranty) { 
      return Warranty.sendRequest() 
       .then(null, function(errorData) { 
        // Log an error here? 
        // Or do something with the error data? 
       }); 
     }] 
    } 
}); 

Bây giờ trong điều khiển của bạn, bạn sẽ muốn kiểm tra xem responseundefined. Nếu đó là undefined thì bạn sẽ biết rằng cuộc gọi tới Warranty.sendRequest() không thành công và bạn có thể hành động tương ứng.

Đối với những gì đáng giá, tôi không đi tuyến đường này. Thay vào đó, tôi đã tiêm dịch vụ $location vào trình xử lý resolve và được chuyển hướng đến trang lỗi nếu cuộc gọi $http bị từ chối.

CẬP NHẬT Chỉ cần nhận thấy rằng trong bộ điều khiển của bạn, bạn được tiêm dịch vụ Warranty khi bạn thay vì phải được tiêm response mà bạn xác định trong resolve của bạn. Điều đó sẽ ngăn chế độ xem của bạn hiển thị cho đến khi Lời hứa được trả lại từ Warranty.sendRequest() được giải quyết.

Các vấn đề liên quan