AngularJS,承诺具有递归功能

时间:2013-12-16 09:27:39

标签: javascript angularjs recursion promise

我正在尝试使用AngularJS承诺/然后使用递归函数。但是没有调用then-function(没有调用error-,success-,notify-callbacks)。

这是我的代码:

递归功能

loadSection2 = function() {

    var apiURL = "http://..."

    var deferred = $q.defer();

    $http({
        method: "GET",
        url: apiURL
    }).success(function(result, status, headers, config) {
        console.log(result);
        loadCount++;
        if(loadCount < 10) {
            newSectionArray.push(result);
            loadSection2(); 
        } else {
            loadCount = 0;
            deferred.resolve();
            return deferred.promise;
        }
    }).error(function() {
        return deferred.reject();
    });
    deferred.notify();
    return deferred.promise;
};

,然后

loadSection2().then(function() {
    console.log("NEW SECTIONS LOADED, start adding to document");
    addContent();
}, function() {
    console.log("ERROR CALLBACK");
}, function() {
    console.log("NOTIFY CALLBACK");
}).then(function() {
    loadScrollActive = false;
});

我认为,至少必须得到第一个通知回调。但是没有回调。 那么不使用递归函数吗?

3 个答案:

答案 0 :(得分:22)

编辑 - 2015年11月11日如果您不关心通知,有一种更清洁的方式:

loadSection2 = function (){
    var apiURL = "http://..."
    return $http.get(apiURL)
        .then(function(response){
            loadCount++;        
            if (loadCount < 10) {
                newSectionArray.push(response.data);
                return loadSection2();
            }
            loadCount = 0;
        });

};

此处提供旧答案:

你可以一直通过承诺。

loadSection2 = function(deferred) {

    if(!deferred){
        deferred = $q.defer();
    }
    var apiURL = "http://..."

    $http({
        method: "GET",
        url: apiURL
    }).success(function(result, status, headers, config) {
        console.log(result);
        loadCount++;
        if(loadCount < 10) {
            newSectionArray.push(result);
            loadSection2(deferred); 
        } else {
            loadCount = 0;
            deferred.resolve();
            return deferred.promise;
        }
    }).error(function() {
        return deferred.reject();
    });
    deferred.notify();
    return deferred.promise;
};

答案 1 :(得分:3)

我想制作一个不会传递“延迟”变量的解决方案,即使我不想说这是一个更好的方法,它也可以,我从中学到了一个(jsfiddle)。 / p>

19 / Aug / 14 - 通过删除f1()中另一个promise的创建,将代码更新为更短的版本。我希望很清楚它与原始问题的关系。如果在评论中没有告诉我。

f1().then(function() {
    console.log("done");
});

function f1(counter) {

    if (!counter) {
        counter = 0;
    }

    counter++;
    console.log(counter);

    return asyncFunc().then(function() {
        if (counter < 10) {
            return f1(counter);
        } else {
            return;
        }
    });

}

function asyncFunc() {
    var deferred = $q.defer();

    $timeout(function() {
        deferred.resolve();
    }, 100);

    return deferred.promise;
}

答案 2 :(得分:0)

Fauphi,

递归是完全可行的,但不是特别“妄想”的方法。

鉴于您有可用的延迟/承诺,您可以动态构建.then()链,该链提供已填充数组的承诺。

function loadSection2(arr) {
    return $http({
        method: "GET",
        url: "http://..."
    }).then(function(result, status, headers, config) {
        console.log(result);
        arr.push(result);
        return arr;//make the array available to the next call to loadSection2().
    }, function() {
        console.log("GET error");
        return $q.defer().resolve(arr).promise;//allow the chain to continue, despite the error.
        //or I think $q's .then() allows the much simpler form ...
        //return arr; //allow the chain to continue, despite the error.
    });
};

var newSectionPromise = $q.defer().resolve([]).promise;//note that the deferred is resolved with an anonymous new array.
//Now we build a .then() chain, ten long, ...
for (var i=0; i<10; i++) {
    newSectionPromise = newSectionPromise.then(loadSection2);
}
// ... and do something with the populated array when the GETs have done their thing.
newSectionPromise().then(function(arr) {
    console.log(arr.length + " new sections loaded, start adding to document");
    addContent(arr);
}, function() {
    console.log("ERROR CALLBACK");
}).then(function() {
    loadScrollActive = false;
});

未测试

newSectionArray现在是匿名创建的,并传递到.then()链,无论单个GET的成功/失败,在最终.then的成功处理程序中出现为arr,其中它传递给addContent()。这样就无需在外部范围内使用成员newSectionArray

稍微重新排列,loadSection2可以匿名,进一步减少添加到外部范围的成员数。

显式通知的需要消失为:

  • 不再有主人被推迟通知
  • GET成功处理程序中的
  • console.log(result);提供了所有必要的通知。