【问题标题】:Angular HttpPromise: difference between `success`/`error` methods and `then`'s argumentsAngular HttpPromise:`success`/`error` 方法和`then` 的参数之间的区别
【发布时间】:2013-04-29 09:55:26
【问题描述】:

根据AngularJS doc,对$http 的调用返回以下内容:

使用标准 then 方法和两个 http 特定方法返回一个 promise 对象:success 和 error。 then 方法有两个参数,一个 success 和一个 error 回调,它们将被一个响应对象调用。 success 和 error 方法采用单个参数 - 分别在请求成功或失败时调用的函数。传递给这些函数的参数是传递给 then 方法的响应对象的解构表示。

除了 response 对象在一种情况下被解构之外,我不明白两者之间的区别

  • 成功/错误回调作为promise.then 的参数传递
  • 作为参数传递给 Promise 的 promise.success/promise.error 方法的回调

有吗?这两种不同的方式传递看似相同的回调有什么意义?

【问题讨论】:

    标签: angularjs promise


    【解决方案1】:

    NB 这个答案实际上是不正确的;正如下面的评论所指出的,success() 确实返回了原始承诺。我不会改变;并留给 OP 编辑​​。


    两者之间的主要区别在于.then() 调用返回一个promise(通过回调返回的值解析),而.success() 是更传统的注册回调方式并且不返回promise。

    基于 Promise 的回调 (.then()) 使链接 Promise 变得容易(进行一次调用,解释结果,然后再进行一次调用,解释结果,再进行一次调用等)。

    .success() 方法是一种简化的、方便的方法,当您不需要链接调用或使用 Promise API 时(例如,在路由中)。

    简而言之:

    • .then() - Promise API 的全部功能,但略显冗长
    • .success() - 不返回承诺,但提供更方便的语法

    【讨论】:

    • 另一个很大的区别是then 回调采用单个参数--响应--而success 和error 采用响应的各个组件作为参数--data, status、header 和 config。
    • @BrandonTilley 完全正确,但问题的作者已经想通了,所以我觉得我不需要在这里重复。
    • 虽然文档没有明确说明,但我们可以推断.success() 方法返回原始的$http promise 对象,因为链$http(...).success(...).error(...) 是可能的。如果看起来是合理的,反向的$http(...).error(...).success(...) 也是可能的,那么.error() 也应该返回原始的promise 对象。 .then() 的显着区别在于它返回一个 new 承诺。
    • $http服务的angular.js源码:promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
    • 请注意,success 已被弃用。来自docs.angularjs.org/api/ng/service/$http#deprecation-noticeThe $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
    【解决方案2】:

    简单 GET 请求的一些代码示例。也许这有助于理解差异。 使用then:

    $http.get('/someURL').then(function(response) {
        var data = response.data,
            status = response.status,
            header = response.header,
            config = response.config;
        // success handler
    }, function(response) {
        var data = response.data,
            status = response.status,
            header = response.header,
            config = response.config;
        // error handler
    });
    

    使用success/error:

    $http.get('/someURL').success(function(data, status, header, config) {
        // success handler
    }).error(function(data, status, header, config) {
        // error handler
    });
    

    【讨论】:

    • 谢谢,但问题更多是关于这些功能的不同之处,或者如果它们做同样的事情,它们同时存在的原因。从文档中可以理解如何使用它们的区别。
    • 我个人喜欢简短的代码示例,因此我将它们发布在这里。 Angular 文档有时会错过简短的精确示例。
    • 重要的是要强调第一个 gist 的响应对象包含第二个 gist 的“数据、状态、标题和配置”这一事实。这意味着响应对象具有额外的一层深度。
    • 将响应值传递给变量data,status,header,config 比简单地返回response 有什么好处吗?
    【解决方案3】:

    只是为了完成,这里是一个指示差异的代码示例:

    成功\错误:

    $http.get('/someURL')
    .success(function(data, status, header, config) {
        // success handler
    })
    .error(function(data, status, header, config) {
        // error handler
    });
    

    然后:

    $http.get('/someURL')
    .then(function(response) {
        // success handler
    }, function(response) {
        // error handler
    })
    .then(function(response) {
        // success handler
    }, function(response) {
        // error handler
    })
    .then(function(response) {
        // success handler
    }, function(response) {
        // error handler
    }).
    

    【讨论】:

    • 太棒了!,你有一个串联有用的例子吗?
    • 这个想法是“then”方法更有用,因为您可以更轻松地一个接一个地编写异步操作。
    【解决方案4】:

    这里已经有一些很好的答案。但值得一提的是所提供的并行性差异:

    • success() 返回原始承诺
    • then() 返回一个新的承诺

    不同之处在于then() 驱动顺序操作,因为每次调用都会返回一个新的承诺。

    $http.get(/*...*/).
      then(function seqFunc1(response){/*...*/}).
      then(function seqFunc2(response){/*...*/})
    
    1. $http.get()
    2. seqFunc1()
    3. seqFunc2()

    success() 驱动并行操作,因为处理程序链接在同一个 Promise 上。

    $http(/*...*/).
      success(function parFunc1(data){/*...*/}).
      success(function parFunc2(data){/*...*/})
    
    1. $http.get()
    2. parFunc1(), parFunc2() 并行

    【讨论】:

    • 请注意,一旦达到then,返回的新承诺响应会导致success 和error 方法消失。此外,对于 http 错误响应(例如 404),http.then(ok, err).then(ok, err) 中的第一个 then 将传递给 err 处理程序,但后面的将传递给 ok 处理程序。基本上http.success().error().success().error() 是可链接的,但 $q 承诺完全不同,因为它们都是关于承诺和具体处理的顺序(而不是 http 请求处理)。在我仔细观察之前,我很难理解这一点。
    • @jimmont success 和 error 不是 Promise 的普通 API,它们被固定在 $http() 的返回值上。
    • 谢谢@event_jr,这对我来说很清楚,并在文档中指出。 (对我来说)不太清楚的是 $q 和 $http 如何解决不同的问题以及返回新的承诺与传递相同的承诺 - 正如您(超级有用的)答案中所指出的那样。
    • 并行是什么意思,因为 JS 是单线程的?你的意思是执行顺序是不确定的吗?
    • @Derek 第二个success 将在第一个执行之后但在从它返回的任何承诺被解决之前执行,而第二个then 将等待。如果您没有返回承诺,那么两者的行为相同。
    【解决方案5】:

    .then() 是可链接的,将等待前一个 .then() 解析。

    .success() 和 .error() 可以链接,但它们会同时触发(所以没有太多意义)

    .success() 和 .error() 非常适合简单的调用(easy maker):

    $http.post('/getUser').success(function(user){ 
       ... 
    })
    

    所以你不必输入这个:

    $http.post('getUser').then(function(response){
      var user = response.data;
    })
    

    但通常我使用 .catch() 处理所有错误:

    $http.get(...)
        .then(function(response){ 
          // successHandler
          // do some stuff
          return $http.get('/somethingelse') // get more data
        })
        .then(anotherSuccessHandler)
        .catch(errorHandler)
    

    如果您需要支持

        .then(successHandler)
        ['catch'](errorHandler)
    

    工作示例:

    这是我以更代码格式写的一些内容,以刷新我的记忆,以了解处理错误等所有内容的方式:

    http://jsfiddle.net/nalberg/v95tekz2/

    【讨论】:

    • 显示“return-another-promise”如何工作的唯一答案
    【解决方案6】:

    官方通告:success 和 error 已被弃用,请改用标准 then 方法。

    弃用通知: $http 遗留承诺方法成功和错误已被弃用。请改用标准 then 方法。如果 $httpProvider.useLegacyPromiseExtensions 设置为 false 然后这些 方法会抛出 $http/legacy 错误。

    link: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

    screenshot: view the screenshot

    【讨论】:

      猜你喜欢
      • 2015-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 2014-10-12
      相关资源
      最近更新 更多