Promise函数无法访问父变量

时间:2016-07-06 17:24:34

标签: javascript angularjs closures

我不熟悉angularjs中promises的使用,我目前在生成某些输出方面遇到困难。我试图使用for循环来生成一个句子数组,每个句子都按“levelName:groupName - description”。

我有一个名为“prodFactory”的工厂,它使用$ http.get通过方法getLevelNames(),getGroupNames(levelName)和getGroupData(groupName)获取levelName,groupName和description。从我的源文件中,我有一个3个levelName的数组,每个都与2个groupNames的数组相关联。运行下面的代码时,我尝试记录值,并得到以下结果:

i = 229,j = 2,data1 =我定义的级别名称,data2 =我定义的组名称。

虽然我能够得到我的关卡和组名,因为i和j的值与for循环定义的关闭,我得到的结果是“undefined:undefined - description”。

有没有得到正确的输出?谢谢!

代码段

prodFactory.getLevelNames().then(function(data1){
            var suggestions = [];
            $scope.data1 = data1;
            for(i=0; i<data1.length; i++){
                prodFactory.getGroupNames(data1[i]).then(function(data2){
                    $scope.data2 = data2;
                    for(j=0; j<data2.length; j++){
                        prodFactory.getGroupData(data2[j]).then(function(data3){
                                $scope.data3 = data3;
                                for(k=0; k<data3[0].length; k++){
                                    console.log(i);
                                    console.log(j);
                                    console.log(data1);
                                    console.log(data2);
                                    suggestions.push($scope.data1[i]+": "
                                    +$scope.data2[j]+" - "+$scope.data3[0][k]);
                                };
                            });
                };
                });
        };
        $scope.getSuggestions = suggestions;
        console.log($scope.getSuggestions);
    });

3 个答案:

答案 0 :(得分:0)

您无法使用嵌套承诺

因为执行顺序不可预测。

答案 1 :(得分:0)

我认为你对关闭有一些误解。所以也许你可以看看Closures。我还建议你阅读IIFE

我们总能尝试的一件事是简化问题。在这种情况下,我们可以先尝试两个级别的问题:我们可以先尝试getLevelNames(),getGroupNames(levelName)。

要解决这个两级问题,我可能会尝试:

prodFactory.getLevelNames()
.then(function(levelNames) {
    var suggestions = [];
    $scope.levelNames = levelNames;
    for(var i=0; i < levelNames.length; i++){ 
        // [IIFE][2]
        (function () {
            var index = i; 
            prodFactory.getGroupNames(levelNames[index])
            .then(function(groupNames) {
                $scope.groupNames[index] = groupNames;
                console.log(index);
                for (var j = 0; j < groupNames.length; ++j) {
                    suggestions.push($scope.levelNames[index]+": "
                                +$scope.groupNames[index][j]");
                }
            });
        })();
    }
    $scope.getSuggestions = suggestions;
    console.log($scope.getSuggestions);
});

答案 2 :(得分:-1)

代码中的最后一个console.log将在任何HTTP请求完成之前执行。这是因为promises总是异步的。

在循环中创建promises会使以后处理结果变得更加困难。您需要$q.all$q.spread或某些Array来添加结果。另外,制作大量HTTP请求也不会有效。您应该始终努力限制请求数量。

我建议制作返回所有级别,组等结果的方法。

prodFactory.getLevelNames().then(function(data1){
  prodFactory.getGroupNames(data1).then(function(data2){
    prodFactory.getGroupData(data2).then(function(data3){
      $scope.suggestions = makeSuggestions(data1, data2, data3)
      console.log($scope.suggestions);
    });
  });
};

请不要创建一个名为getSuggestions的变量。看起来它的方法/功能不是变量。