2016-01-06 63 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