多个$ http承诺使用工厂,角度

时间:2014-08-29 14:40:46

标签: javascript angularjs factory

我正在尝试在工厂中调用多个$ http请求,我用它来清除多个输入数据并设置默认选择。我想在完成其中所有3个调用一个承诺后,调用真实表单数据(如果有的话,有时候不会在哪种情况下它将无效)来覆盖默认值。

所以这是我对此的尝试 -

工厂 我建立了一个工厂来调用所有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个调用合并到一个地方,并在完成后完成承诺。我想我需要返回数据,但如果我可以在工厂中定义控制器的范围,那将是非常好的。我仍然用棱角分明,所以任何/所有的指导都会非常感激。感谢您的阅读!!

3 个答案:

答案 0 :(得分: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.all文档:https://docs.angularjs.org/api/ng/service/$q

答案 1 :(得分:1)

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

示例此处fiddle

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

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

答案 2 :(得分:1)

你可能想看一下角度的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 $的所有方法,然后调用"然后"结果执行逻辑的第二部分

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];
 });
});