从嵌套的http.put返回值

时间:2016-01-06 11:30:50

标签: angularjs angularjs-service angularjs-http

如何将响应对象从http.put返回到控制器作为TestFunction的返回值? 来自http.get的响应打印好,但putResponse未定义。在调试期间,我可以看到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 个答案:

答案 0 :(得分: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 */ })

答案 1 :(得分: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()创建两个promise,然后返回$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);
  });
}