AngularJS - 为什么用$ http承诺($ q)?

时间:2014-12-10 12:42:22

标签: angularjs deferred

我在从jQuery转换几年后正在学习AngularJS。有些位更加直观。有些不那么多:)。

我试图了解承诺的使用,特别是使用$ http的$ q,并且似乎没有太多关于这两个组合的信息,我可以找到。

为什么我会使用promises代替成功/错误回调?他们都在现实中使用回调,那么为什么承诺会更好?例如。我可以设置一个get(...)函数,如下所示:

function get(url, success, error) {
    success = success || function () {};
    error = error || function () {};

    $http.get(url)
        .success(function (data) {
            success(data);
        })
        .error(function (error) {
            error(error);
        });
}

get('http://myservice.com/JSON/',
    function () {
        // do something with data
    },
    function () {
        // display an error
    }
);

哪个好(?)因为它让我完全控制正在发生的事情。如果我拨打get(...),那么我可以控制get被调用的任何成功/错误。

如果我将此转换为使用承诺,那么我得到:

function get(url) {
    return $http.get(url)
        .then(function (data) {
            return data;
        },
        function (error) {
            return error;
        });
}

get('http://myservice.com/JSON/')
    .then(function (data) {
        // do something with data
    });
    // cannot handle my errors?

哪个是浓缩的,我同意;我们也不必明确担心成功/错误回调,但我似乎已经失去了对我的错误回调的控制 - 因为我无法配置第二个回调来处理错误。

这意味着如果我在一个可供多个控制器使用的服务中使用此功能,那么我无法更新UI以提醒用户出错。

我错过了什么吗?承诺是首选的是有原因吗?我找不到一个例子。

2 个答案:

答案 0 :(得分:24)

通常,您将使用回调来处理Javascript中的异步任务;

$.get('path/to/data', function(data) {
  console.log(data);
});

它工作正常,但是当你进入什么叫做“回调地狱”时会开始变得复杂;

$.get('path/to/data', function(data) {
  $.get('path/to/data2' + data, function(data2) {
    $.get('path/to/data3' + data2, function(data3) {
      manipulate(data, data2, data3);
    }, errorCb);
  }, errorCb);
}, errorCb);

替代方案是使用promises和deferred对象;

Deferreds - representing units of work
Promises - representing data from those Deferreds

坚持这个议程可以在每个极端的asynctask案例中为你提供帮助:

  1. 您需要定期调用,需要从服务器获取数据,操作数据并返回范围
  2. 你有多个电话,每个电话都依赖于珍贵的电话(cahin策略)
  3. 您希望发送多个(并行)调用并在1个块中处理它们的成功
  4. 您希望对代码进行组织处理(防止处理控制器上的处理结果)
  5. 您的任务是使用$ q和$ http

    处理的最简单的任务
    function get(url) {
        var deferred = $q.defer();
        $http.get(url)
            .success(function (data) {
                deferred.resolve(data);
            })
            .error(function (error) {
                deferred.reject(error);
            });
    
        return deferred.promise;
     }
    

    调用服务功能是相同的

    get('http://myservice.com/JSON/')
    .then(function (data) {
        // do something with data
    });
    // cannot handle my errors?
    

答案 1 :(得分:1)

您可以像这样处理错误:

get('http://myservice.com/JSON/')
    .then(function (data) {
        // do something with data
    },
    function (error) {
        //do something with error
    });

但遗憾的是,由于您已经发现错误,因此最终错误不会被触发。成功也会遇到同样的问题。

要实现这一点,你需要使用$ q。

function get(url) {
    var deferred = $q.defer();

    $http.get(url)
        .success(function (data) {
            deferred.resolve(data);
        })
        .error(function (error) {
            deferred.reject(error);
        });

    return deferred.promise;
}

此外,无需传递成功和错误函数,因为您可以使用promises。