【问题标题】:AngularJS passing more than one value to promise's success callbackAngularJS 将多个值传递给 Promise 的成功回调
【发布时间】:2015-12-06 22:55:29
【问题描述】:

我有如下服务方式:

ResourcesService.prototype.list = function ()
{
      var deferred = q.defer();
      var settings = fetchSettings();
      restService.getAll(resourceName, settings)
      .then(function (response) {
          deferred.resolve(response.data, {
               count: response.headers('cr_count'),
               total: response.headers('cr_total'),
               last: response.headers('cr_last')
          });
      }, function (error) {
          deferred.reject(error.statusText);
      });
      return deferred.promise;
}

如您所见,我将两个值传递给deferred.resolve,它们是response.data 和一个元数据对象。

在我的调用堆栈中:

//"scenes" is an object that inherits from ResourcesService
scenes
.withLanguage('en-us')
.sort('creation')
.size(2)
.list()
.then(function (firstPage, metadata) {
     //firstPage is the "response.data" from previous method
     //metadata is undefined, but should be an object with all the values from the headers
});

为什么metadata 未定义?我调试了ResourcesService 并且标题被读取得很好,但是作为deferred.resolve 的参数传递的对象没有被委托给我的回调函数。

deferred.resolve 是否只支持将一个参数传递给回调?我是否必须将此元数据与响应一起放在同一个对象中?

【问题讨论】:

标签: javascript angularjs promise deferred


【解决方案1】:

您不能将多个参数传递给then 回调,只有一个是预期和考虑的。然而,你可以做的是用一个对象来解决你的承诺。例如:

ResourcesService.prototype.list = function () {

    var settings = fetchSettings();
    return restService.getAll(resourceName, settings).then(function (response) {
        return {
            data: response.data, 
            metadata: {
                count: response.headers('cr_count'),
                total: response.headers('cr_total'),
                last: response.headers('cr_last')
            }
        };    
    }, function (error) {
        throw new Error(error.statusText);
    });
}

请注意,我还在您的代码中修复了deferred anti-pattern,您不需要虚拟延迟对象,因为您已经承诺可以返回。

然后你会这样使用它:

scenes
.withLanguage('en-us')
.sort('creation')
.size(2)
.list()
.then(function (response) {
    var firstPage = response.data,
        metadata =  response.metadata;
});

【讨论】:

  • 这个方法比我的好很多,但是为什么出现错误时抛出异常?我尝试返回error.statusText,但我的错误回调从未执行。相反,我的成功回调被调用。如何在不使用q.reject 的情况下调用错误回调?
  • 这正是我要抛出的原因:因为如果你返回 - 这意味着你处理了失败,所以有点恢复,然后在随后的回调中你不会进入错误处理程序 - 因为你已经处理了错误。所以在这种情况下,如果你想沿着链传播错误,你要么 $q.reject 要么抛出。如果您愿意,您甚至可以只 throw error.statusText;
  • 我明白了。谢谢您的回答!。我最终按照你的方式做,我比以前更喜欢它,而且我不再依赖 $q 服务。
【解决方案2】:

虽然@dsfq 关于不使用多个参数进行解析是正确的,但如果您使用q,您也可以将解析后的值包装在一个数组中并使用.spread() 而不是.then() 将它们拆分论据。

创建:

  .then(function (response) {
      // Resolve with a single array
      deferred.resolve([response.data, {
           count: response.headers('cr_count'),
           total: response.headers('cr_total'),
           last: response.headers('cr_last')
      }]);
  }

消耗:

scenes
.withLanguage('en-us')
.sort('creation')
.size(2)
.list()
// .spread() instead of .then()
.spread(function (firstPage, metadata) {
  // Works as expected
});

【讨论】:

    猜你喜欢
    • 2015-12-04
    • 2013-10-07
    • 2014-09-17
    • 2015-08-31
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    相关资源
    最近更新 更多