多个$http与promise使用工厂,angular

multiple $http with promise using factory, angular

本文关键字:工厂 angular promise http 多个      更新时间:2023-09-26

我正试图在一个工厂中调用多个$http请求,我正在使用该请求来用数据清除多个输入并设置默认选择。然后,我想在完成所有这三个操作后调用promise,以调用真实形式的数据(如果有,有时不会有,在这种情况下它什么都不会做),从而覆盖默认值。

这是我的尝试-

工厂我建立了一个工厂来调用所有3个输入和它们的默认值(我正在单独发送它们,我现在无法更改)。它看起来像这样:

.factory("getDefaults", function() {
return {
    instructions: function() {
        $http({
        method: "GET",
        url: "/getStringDropdown/materials"
    })
    .success(function(data, status, headers, config){
        $scope.instructions.materials = data.text;
    });
    $http({
        method: "GET",
        url: "/getStringDropdown/reinforce"
    })
    .success(function(data, status, headers, config){
        $scope.reinforce = data.options;
        $scope.instructions.reinforce = $scope.reinforce[data.default];
    });
    $http({
        method: "GET",
        url: "/getStringDropdown/procedure"
    })
    .success(function(data, status, headers, config){
        $scope.procedures = data.options;
        $scope.instructions.procedures = $scope.procedures[data.default];
    });
     //return data here? 
    }
  };
})

我的问题是——我必须在这里返回数据吗?我也可以在这里定义正在使用的范围(在实际控制器中相当于)。我确信这是错误的,但我找不到一个好的例子来说明如何正确地构建这样的东西。

控制器中的调用

所以我是控制器,我想我会尝试这样的东西——

    getDefaults.instructions().then(function(){
            //possible return data here
            //AFTER data is flushed out call farm data
    $http({
        method: "GET",
        url: "/getSavedFormData/formID"
    })
    .success(function(data, status, headers, config){
        $scope.instructions.materials= data.materials;
        $scope.instructions.procedures = $scope.procedures[data.procedure];
        $scope.instructions.reinforce = $scope.reinfoce[data.reinforcement];
    });
        });

大局如此——我正试图让这3个调用运行并填充,然后是第二个调用。我不确定什么可能是最好的方法,也不确定什么不是最好的方法。工厂似乎是有意义的,因为它试图将3个调用合并到一个地方,并承诺当它们都完成时。我想我需要返回数据,但如果我能在工厂中定义控制器的作用域,那就太好了。我仍然保持着我的角度,所以任何/所有的指导都将不胜感激。感谢阅读!!

您的服务不知道您的$scope是开箱即用的,您可能也不希望它是这样,因为服务的全部目的是帮助您的代码模块化。

您可能想要做的是从您的服务返回$http承诺,这样您的.success()回调就可以通过闭包(位于控制器内部)在$scope上设置模型。

所以你的工厂会更像这样:

.factory("getDefaults", function() {
  return {
    instructions: $http({ method: "GET", url: "/getStringDropdown/materials" })
  }
});

如果你真的认为你永远不需要单独的http调用,而你只关心它们何时全部解决。你可以返回一个$q.all()承诺,当它们都解决时就会解决:

.factory("getDefaults", function($http, $q) {
  var promise1 = $http({ method: "GET", url: "/getStringDropdown/materials" });
  var promise2 = $http({ method: "GET", url: "/getStringDropdown/materials" });
  var promise3 = $http({ method: "GET", url: "/getStringDropdown/materials" });
  return {
    data: $q.all([promise1,promise2,promise3]),
    anotherCall: $http.get('/anothercallUrl')
  }
});

所以现在从你的控制器你可以做:

function myCtrl($scope,getDefaults){
   getDefaults.data.then(function(data){
     //access all three of your promises, their data, and set $scope models here
     getDefaults.anotherCall.success(function(data){
       //or another http call
     });
   };
}

$q.此处的所有文档:https://docs.angularjs.org/api/ng/service/$q

在工厂中使用作用域不是一个好主意,我建议不要使用,关于应该使用$q.all 的多个http调用

小提琴的例子

对于每个调用,您应该创建延迟对象,将其推入数组,然后使用

$q.all(deferesArray).then(
      function(resp){
         // all requests are resolver , resp is array with resolved datas
        }
  )

您可能需要了解angular的q$(https://docs.angularjs.org/api/ng/service/$q)

1.)创建必须完成"第一个"的前三个承诺

 var deferred = $q.defer();
$http({
    method: "GET",
    url: "/getStringDropdown/procedure"
})
.success(function(data, status, headers, config){
    deferred.resolve(data);
});
var promise1 = deferred.promise;

2.)使用q$的all方法,然后对结果调用"then"来执行逻辑的第二部分

q$.all([promise1, promise2, promise3])
.then(function(results) {
 $http({
    method: "GET",
    url: "/getSavedFormData/formID"
  })
  .success(function(data, status, headers, config){
    $scope.instructions.materials= data.materials;
    $scope.instructions.procedures = $scope.procedures[data.procedure];
    $scope.instructions.reinforce = $scope.reinfoce[data.reinforcement];
 });
});