Return 来自嵌套 http.put 的值

Return value from nested http.put

如何 return 从 http.put 响应对象到控制器作为来自 TestFunction 的 return 值? 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);

    }

$http.get$http.put 与其余代码异步执行。 你从异步调用中得到了 console.log。所以它在 return.

之前被调用

此外,如果您想要 putResponse return 编辑到 "caller",您必须 return 同时 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 */ })

一种方法是使用 $q.all() 到 return 多个承诺。

工作 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() 创建两个承诺,然后 returns $q.all(promises)。这 return 是一个单一的承诺,您可以通过 .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);
  });
}