【问题标题】:multiple $http with promise using factory, angular多个 $http 承诺使用工厂,角度
【发布时间】:2014-08-29 14:40:46
【问题描述】:

我试图在一个工厂中调用多个 $http 请求,我用它来清除多个输入数据并设置默认选择。一旦所有这三个都完成后,我想调用一个承诺来调用真实的表单数据(如果有的话,有时不会在这种情况下它什么都不做)来覆盖默认值。

所以这是我的尝试-

工厂 我建立了一个工厂来调用所有 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 个调用合并到一个地方,并在它们全部完成后做出承诺。我在想我需要返回数据,但如果我可以在工厂中定义控制器的范围,那就太好了。我仍然对角度有所了解,因此非常感谢任何/所有指导。感谢阅读!!

【问题讨论】:

标签: javascript angularjs factory


【解决方案1】:

您的服务不知道您的 $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

【讨论】:

  • 这很好,感谢您的帮助。有没有办法做类似的事情。然后在我设置范围之后调用最后一个 $http?
  • 当然,您可以进行另一个返回另一个承诺的服务调用。 getDefaults.anotherCall.success(function(data){}));
  • 太棒了,谢谢。我是否也可以将实际的 $http 放在那里而不是另一个对服务的调用?
  • 当然可以,这就是依赖注入的美妙之处。只需将 $http 添加到您的控制器依赖项并从那里运行它。
【解决方案2】:

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

fiddle 中的示例

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

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

【讨论】:

    【解决方案3】:

    你可能想看看 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];
     });
    });
    

    【讨论】:

    • 好吧,这看起来真的很棒。我在哪里将数据放在前 3 个范围内?例如-您使用过程显示的延迟调用,我需要使用数据来执行此操作 $scope.procedures = data.options; $scope.instructions.procedures = $scope.procedures[data.default];。我会把它放在哪里?谢谢!!
    • promise 接收到的 "results" 参数包含一个结果对象数组,按照前 3 个 promise 的传入顺序。所以,$scope.procedures = results[2].options ;比如……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    相关资源
    最近更新 更多