2016-07-28 47 views
1

我誤解了承諾,最後呢?角度承諾返回404,最終不會觸發

我發佈到尚未構建的API。它返回一個404 - 正如我所期望的那樣 - 但控制器函數AdminManifestService.postManifest永遠不會結束,所以我有一個微調(永遠綁定到vm.processingButton)。

它不應該一收到404就返回失敗的承諾嗎?

控制器:

vm.sendManifest = function() { 
     vm.processingButton = true; 
     var manifest = vm._buildManifest(); 
     AdminManifestService.postManifest(manifest) 
      .then (
       function success(response) { 
        toastr.success("Manifest has been sent."); 
       }, 
       function fail(response) { 
        toastr.error(response.data); 
       } 
      ) 
      .finally(function(){ 
       vm.processingButton = false; 
      } 
     ); 
    } 

服務:

function adminManifestService($http, $q, ngAuthSettings) { 

    var dataSource = 'api'; 

    // GET User Markups 
    var _postManifest = function (data) { 

     return $q (function(resolve, reject) { 
      switch (dataSource) { 
       case 'api': //staging - live api data 
        return $http({ 
         method: 'post', 
         url: serviceBase + 'api/Admin/Manifest/', 
         data: data 
        }).then(function(results) { 
         resolve(results.data); 
        }); 
        break; 
       default: // dev - local json 
        resolve(); 
      } 
     }); 
    }; 

    adminManifestService.postManifest = _postManifest; 

    return adminManifestService; 
} 
+0

'finally'是'$ q'承諾的方法,即OP使用。請參閱[文檔](https://docs.angularjs.org/api/ng/service/$q) – Iso

+0

恐怕我無法解析這句話。問題是什麼?解決辦法是什麼? – DaveC426913

+0

有一個評論(現在刪除)詢問你是如何來到'finally'的,因爲它不屬於Promises規範。它確實不是規範的一部分,但帶有'$ q' :) – Iso

回答

2

你永遠不會拒絕你的adminManifestService的承諾,所以$http拒絕被吞噬。

當心!你是promise anti-pattern的受害者。

相反包裹你的$http承諾與$q的,簡單地返回它:

var _postManifest = function (data) { 
    if (dataSource !== 'api') { 
    return $q.resolve(); 
    } 

    return $http({ 
    method: 'post', 
    url: serviceBase + 'api/Admin/Manifest/', 
    data: data 
    }).then(function(results) { 
    return results.data; 
    }); 
}; 

,您還可以在這裏也添加errorCallback

var _postManifest = function (data) { 
    if (dataSource !== 'api') { 
    return $q.resolve(); 
    } 

    return $http({ 
    method: 'post', 
    url: serviceBase + 'api/Admin/Manifest/', 
    data: data 
    }).then(function(results) { 
    return results.data; 
    }, function(results) { 
    // Note that we need to return a rejected promise 
    return $q.reject(results.data); 
    }); 
}; 

這樣就可以使用最少的爲您服務工作:

adminManifestService.postManifest(manifest) 
    .then(function() { 
    toastr.success("Manifest has been sent."); 
    }, toastr.error)  // You can just send `toastr.error` here 
    .finally(function(){ 
    vm.processingButton = false; 
    }); 
+0

嗯。我原來並沒有那個$ q,當我遇到終於遇到的問題時,我將它貼在SO上,有些人認爲這是解決方案。所以現在你建議我把它拉回來。好的,我會嘗試。謝謝。 – DaveC426913

+1

請閱讀我上面提供的鏈接; '$ http'已經返回一個承諾,這裏你不需要'$ q'(除非你想拒絕更新的拒絕 - 見第二個代碼塊):) – Iso

+0

啊。好。我知道爲什麼$ q現在在那裏。因爲服務不一定是一個承諾。更新OP。對不起,關於大雁追逐。 我想,因爲我有一個本地實現,我將不得不使用它。 – DaveC426913

0

$http服務退貨promise本身,這意味着它不需要包裝任何東西在$q。這裏工作Plunker與概念證明的概念。

function adminManifestService($http, $q, ngAuthSettings) { 

    var dataSource = 'api'; 

    // GET User Markups 
    var _postManifest = function (data) { 

     switch (dataSource) { 
      case 'api': //staging - live api data 
       return $http({ 
        method: 'post', 
        url: serviceBase + 'api/Admin/Manifest/', 
        data: data 
       }) 
       break; 
      default: // dev - local json 
       return new Promise(function(resolve){ 
        resolve({data:"dev data"}) 
       }) 
     } 
    }; 

    adminManifestService.postManifest = _postManifest; 

    return adminManifestService; 
} 

控制器

vm.sendManifest = function() { 
    vm.processingButton = true; 
    var manifest = vm._buildManifest(); 
    AdminManifestService.postManifest(manifest) 
     .then (
      function success(response) { 
       toastr.success("Manifest has been sent."); 
       vm.processingButton = false; 
      } 
     ) 
     .catch(function(err){ 
       toastr.error(err); 
       vm.processingButton = false; 
     }); 
} 
+0

新增Plunker https://plnkr.co/edit/ySmA3Rd5DB6JQp50NVlM?p=preview – oKonyk