【问题标题】:angularjs $q & $http about promiseangularjs $q & $http 关于承诺
【发布时间】:2016-04-24 11:52:46
【问题描述】:

关于官方文档中的$http:

$http API 基于 $q 公开的 deferred/promise API 服务。

$http 服务是一个接受单个参数的函数——a 配置对象——用于生成 HTTP 请求和 返回一个承诺

那么下面的代码是什么意思:

var deferred = $q.defer();
var promise = deferred.promise;
var progress;
$http.get("https://api.github.com/repos/angular/angular.js/pulls")
.success(function(data){
    var result = [];
    for(var i = 0; i < data.length; i++){
        result.push(data[i].user);
        progress = (i+1)/data.length * 100;
        deferred.notify(progress);
    }
    deferred.resolve(result);
    })
.error(function(error){
    deferred.reject(error);
});
return promise;

如果 $http 返回一个 Promise,我为什么要使用 $q 返回一个 Promise?

【问题讨论】:

  • 嗯。这很奇怪。通常你会做类似.success().then()的事情。我想知道他们的文档是否已经过时了,或者由于某种原因 Angular 不支持 Promise 链接。
  • @AR7,Angular 确实支持承诺链,只是不支持 success() 方法,该方法现在已弃用。有关详细信息,请参阅下面的我的答案。使用$http.get().then() 一切正常。

标签: angularjs http promise angular-promise


【解决方案1】:

$http 正在返回一个承诺,我们使用它并因此获得“成功”(也可以使用“那么”)。如果您在服务中使用此 $http 调用并从控制器调用此服务方法,那么您将希望从该方法返回一个承诺,因此您可以使用 .then 和 .catch 等

【讨论】:

    【解决方案2】:

    一个延迟的新实例是通过调用$q.defer()来构造的。 延迟对象的目的是公开关联的 Promise 实例以及 API

    可用于指示成功不成功完成,以及状态 任务。

    $q 与 $rootScope.Scope Scope 模型观察机制以角度方式集成,这意味着可以更快地将分辨率或拒绝传播到您的模型中,并避免不必要的浏览器重绘,这会导致 UI 闪烁。

    参考:官方文档

    【讨论】:

      【解决方案3】:

      $http 服务的推荐使用方式如下:

      $http({
        method: 'GET',
        url: '/someUrl'
      }).then(function successCallback(response) {
          // success code here
        }, function errorCallback(response) {
          // error handling code here
        });
      

      在这种情况下,您不必返回新的 Promise,只需将调用结果返回给 then(),就像您所期望的那样。

      但是,success() 方法是一种方便的方法,它已经将响应对象的字段作为单独的参数传递:

      .then(function(response) {
        // do something with response.data, response.status, etc.
      })
      

      对比

      .success(function(data, status, headers, config) {
        // do something with data, status, etc.
      })
      

      但是,与then() 相比,success() 不返回承诺。我不建议使用它,我刚刚在the docs 中看到它现在已被弃用。

      更新:我认为在您提供的示例中构造另一个承诺的原因不是可以使用success(),而是可以调用deferred.notify(progress)。如果不显式创建另一个 Promise,您将无法访问 deferred 对象。

      【讨论】:

      • 返回一个promise的是$http(),而不是success()
      • 什么意思? $http.get() 返回一个承诺。如果您在此承诺上调用 .then(),您将获得另一个承诺(例如,您可以从您的函数中返回)。但是,success() 不会返回承诺。所以如果你想使用success(),你必须用$q.defer()创建另一个promise并手动将它们连接在一起。
      • @kuma,我更新了我的答案。是否清楚必须如何更改您的代码以避免显式创建另一个承诺?如果没有,我会将其添加到我的答案中。
      • 3q!明白你的意思。根据你给的,我看一下官方文档,找到下面的词: 这个方法 - 然后返回一个新的承诺,它通过successCallback的返回值,errorCallback(除非该值是一个承诺,其中情况下,它是使用承诺链接在该承诺中解决的值来解决的)。我确实需要动手练习才能深入理解。
      • 如果我在 promise 上使用 'then' 方法,我总是会得到一个 promise
      猜你喜欢
      • 1970-01-01
      • 2013-05-02
      • 2013-09-11
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 2014-07-06
      • 1970-01-01
      相关资源
      最近更新 更多