【问题标题】:Angular JS: Storing data on a promiseAngular JS:在承诺上存储数据
【发布时间】:2013-08-20 12:01:32
【问题描述】:

我的问题是我不知道在哪里存储我需要在 http 请求的最终回调中访问的数据。在 jQuery 中,我只需执行以下操作

var token = $.get('/some-url', {}, someCallback);
token.oSomeObject = {data: 'some data'};

function someCallback( data, status, token ){
     token.oSomeObject.data // 'some data'
}

我使用令牌来存储请求特定的数据。

现在我发现在 Angular 中实现这一点的唯一方法是将数据存储在实际配置中:

var config = {
    url: '/some-url',
    method: 'GET',
    oSomeObject: { data: 'some data' }
};
$http(config).success(someCallback);

function someCallback( data, status, headers, config ){
     config.oSomeObject.data // 'some data'
}

一方面,这会阻止您使用简写调用($http.get,$http.post),我还发现在将调用包装在特定服务模块中时,它是一种更加突兀的方式。

还有其他方法吗?

更新澄清

我可能只是在这里遗漏了一些简单的东西,不了解如何正确使用 Promise API,但为了确保我们在同一页面上,让我为您提供有关该问题的更多详细信息。

我有 2 个文件:1) Controller.js 2) AjaxServices.js(所有 ajax 调用在这里都定义为服务上的方法)。

AjaxServices.js 看起来像这样:

app.service('AjaxService', function( $http ){
     var self = this;

     this.createUser = function( oUser, fSuccessCallback ){
          return $http.put('/api/user', {oUser: oUser})
                       .success(fSuccessCallback);
     }
}

Controller.js 看起来像这样:

app.controller('MyController', function( $scope, AjaxServices ){
     $scope.saveUser = function( oUser ){
          var oPromise = AjaxServices.createUser( oUser, $scope.onUserSaved );

          oPromise.oUser = oUser // this is how I solve it in jQuery.ajax. The oPromise
                                 // is then sent as the token object in the onUserSaved
                                 // callback
     }
     $scope.onUserSaved = function( oStatus, status, headers, config ){
          oStatus.id // here is the id of the newly created user 
                     // which I want to now hook on to the oUser local object

     }
}

您将如何使用 promise API 实现相同的目标?

【问题讨论】:

  • 您可以在简写调用中设置配置:$http.get(url, config)。更多信息:docs.angularjs.org/api/ng.$http#get
  • 只是将其存储在(变量)范围内?您可以从回调函数访问config 变量,因为它们在同一范围内声明 - 只需省略会影响外部变量的参数。

标签: javascript angularjs


【解决方案1】:

更新 2。关于更新代码的一些注释: 您不必将回调传递给服务。这有效地扼杀了承诺的目的。让服务完成其工作,而无需将其与任何数据消费者耦合。

app.service('AjaxService', function( $http ){
    var self = this;

    this.createUser = function( oUser ){
      return $http.put('/api/user', {oUser: oUser});
    }
}

现在服务不关心回调,这意味着您可以将多个回调附加到同一个服务 $http 调用。好的,让我们继续讨论服务数据消费者,在本例中是控制器:

app.controller('MyController', function( $scope, AjaxServices ){
  $scope.saveUser = function( oUser ){
    var oOriginalPromise = AjaxServices.createUser( oUser );
    //lets modify the orginal promise to include our oUser
    var oModifiedPromise = oOriginalPromise.then(function(response) {
      response.oUser = oUser; 
      return response;
    });
    //in the code above we've chained original promise with .then,
    //modified response object and returned it for next promise to receive
    //at the same time, .then created a new promise

    //finally, after modifying our response, we can pass it to the desired callback. 
    //note, that .success and .error are $http specific promise methods, 
    //in all other cases use .then(fnSuccess, fnError)
    oModifiedPromise.then($scope.onUserSaved); 
  }
  $scope.onUserSaved = function(responseWithUser) {
    responseWithUser.oUser;
  }
}

当然,这仍然有点尴尬,因为 oUser 可以保存在控制器的作用域中,并且可以在 $scope.onUserSaved 中直接从那里访问。

更新。我会澄清我的答案。您可以在任何范围、任何地方链接 Promise。这是另一个通过服务注入令牌的示例:

myModule.factory('Service', function($http) {
   return new function() {
      this.getData = function() {
        return $http.get(url).then(function(response) {
          response.token = myToken;
          return response;
        }
      }
   }
});

您甚至可以在您的服务不知道的情况下扩展或包装 $http 服务并在响应中注入令牌。

如果你对所有请求都这样做,也许 $httpInterceptor 会更合适。阅读更多关于拦截 http 调用 here

原答案

由于$http 为您提供了promise,您可以将其链接到另一个promise,该promise 将在响应中注入令牌:

myModule.factory('Service', function($http) {
   return new function() {
      this.getData = function() {
        return $http.get(url);
      }
   }
});

//in controller or other service:
var myToken;
var tokenizedPromise = Service.getData().then(function(response) {
  response.token = myToken;
  return response;
});

promise 的最终消费者也可以访问令牌

【讨论】:

  • 感谢您的回答,但如果我在这里错了,请纠正我,但这不是回调函数可以访问 myToken 的唯一原因,因为它是在父范围内定义的?我的服务位于不同的文件中,然后我传递回调,即:ajaxCall(param,successCallback)。这意味着回调与最初调用的范围不同(js 术语不是角度),因此无法访问 myToken。
  • 感谢您的回答。我仍然不在那里,但如果您愿意再试一次,我已经添加了更多信息。
  • 感谢您的更新。我不将其存储在范围内的原因是为了在调用返回之前创建另一个。我已经阅读了有关如何正确处理角度承诺的一些内容。再次感谢。
猜你喜欢
  • 2014-04-29
  • 2016-06-21
  • 2015-11-27
  • 2016-02-21
  • 2021-05-04
  • 2014-02-02
  • 1970-01-01
  • 2016-12-19
  • 2023-03-20
相关资源
最近更新 更多