AngularJS,promise带有递归函数

AngularJS, promise with recursive function

本文关键字:递归函数 promise AngularJS      更新时间:2023-09-26

我正在尝试将AngularJS promise/then与递归函数一起使用。但是没有调用then函数(没有调用error、success和notify回调)。

这是我的代码:

递归函数

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

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

编辑-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;
};

我想做一个不传递"递延"变量的解决方案,尽管我不会说这是一个更好的方法,但它确实有效,我从中学到了一个(jsfiddle)。

2014年8月19日-通过删除在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;
}

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);提供了所有必要的通知