2016-01-06 111 views
0

如何將http.put中的響應對象作爲TestFunction的返回值返回給控制器? 來自http.get的響應打印成功,但putResponse未定義。在調試期間,我可以看到http.put更新服務器上的數據。來自嵌套http.put的返回值

testFunction: function (url, data) { 
     var etag; 
     var putResponse; 
     $http.get(url).then(function successCallback(response) { 
      if (response.data != null) { 
       etag = response.headers(['etag']); 
       $http.put(url, data, { headers: { 'If-Match': etag } }).then(function successCallback(response) { 
        putResponse = response; 
       }, function errorCallback(response) { 
        // handle error 
       }); 
      } 
      else { 
       // handle error 

      } 

     }, function errorCallback(response) { 
      // handle error 

     }); 
     console.log(putResponse); 

    } 

回答

2

$http.get$http.put從代碼的其餘部分異步地執行。 你有console.log不在異步調用。所以它在返回之前被調用。

而且如果你想putResponse返回到「來電者」,你必須同時返回putResponse和承諾:

testFunction: function (url, data) { 
     var etag; 
     var putResponse; 
     var promise = $http.get(url).then(function successCallback(response) { 
      if (response.data != null) { 
       etag = response.headers(['etag']); 
       return $http.put(url, data, { headers: { 'If-Match': etag } }) 
      } 
      else { 
       // handle error 
       // $q.reject();  
      } 

     }).then(function successCallback(response) { 
      putResponse = response; 
      console.log(putResponse); // this gets called after the server responds (defined) 
      return putResponse; 
     }) 
     ["catch"](function (response) { 
       // handle error 
     }); 

     console.log(putResponse); // this gets called before the server responds (undefined) 
     return promise; 
    } 

現在你可以使用

tesFunction(arg1, arg2).then(function(response){ /* in here you have response defined */ }) 
+0

感謝,testFunction是現在好了,對於putResponse控制檯輸出是OK了。我無法返回putResponse與 testFunction(url,data).then(函數(響應){/ *在這裏你有響應定義* /})...只有來自get的響應被顯示? – playerone

+1

是的,你是對的我已經更新了我的答案。通過這種方式,get中的if還必須返回承諾,否則您將會出現錯誤。 – koox00

+0

是的,這將會訣竅!響應已成功返回給調用者。 總結:首先你必須返回putResponse,然後返回承諾,並且必須處理錯誤。 – playerone

2

一種方法是使用$q.all()返回多個承諾。

工作的jsfiddle:https://jsfiddle.net/sscovil/waxL8Lt8/

在該示例中,我使用的是$httpProvider攔截嘲笑HTTP響應;這與你所需要的不相關,只是爲了說明。

最重要的一點是myRestService功能:

function myRestServiceFactory($http, $q) { 
    return function() { 
    var deferredGet = $q.defer(); 
    var deferredPut = $q.defer(); 
    var promises = {}; 

    promises.get = deferredGet.promise; 
    promises.put = deferredPut.promise; 
    $http.get('https://example.com').then(onGetSuccess, onGetError); 

    return $q.all(promises); 

    function onGetSuccess(response) { 
     if (response.data != null) { 
     var etag = response.headers(['etag']); 
     var config = { 
      headers: {'If-Match': etag} 
     }; 
     $http.put('https://example.com', {}, config) 
      .then(onPutSuccess, onPutError); 
     deferredGet.resolve(response); 
     } else { 
     deferredGet.reject(response); 
     } 
    } 

    function onGetError(error) { 
     deferredGet.reject(error); 
    } 

    function onPutSuccess(response) { 
     deferredPut.resolve(response); 
    } 

    function onPutError(error) { 
     deferredPut.reject(error); 
    } 
    } 
} 

請注意,它使用$q.defer()創建兩個承諾,然後返回$q.all(promises)。這將返回一個承諾,你可以通過.then()附加一個回調,並且回調將得到地圖上承諾的反應是這樣的:

function MyController($scope, myRestService) { 
    $scope.values = {}; 
    myRestService().then(function (values) { 
     $scope.values.get = JSON.stringify(values.get); 
     $scope.values.put = JSON.stringify(values.put); 
    }); 
} 
+0

這是另一種方法。到目前爲止,我一直在避免使用$ q.defer,但是解釋起來很簡單! 根據您的意見,哪種方法最好(比較容易)或上面的(不使用$ q)? – playerone

+0

哪個更容易?這是主觀的。但是我認爲在閱讀代碼時我的方法更容易遵循。 –

+0

好方法!不同之處在於,你在這裏只返回你的雙方承諾。可讀性只依賴於匿名函數的命名,您可以使用這兩種方法。 – koox00