如何重复.then
子句作为循环?我需要等待.then子句承诺解决,然后如果没有满足退出条件,我需要再次重复相同的操作......直到满足退出条件。
我的用例是重复ajax GET调用多个“页面”数据,直到检索完所有数据。
我可以按如下方式简化和模拟问题。这是我希望.thenRepeat
的.then条款:
.then(function(retData) {
namesList.push.apply(namesList, retData); // accum data into list
queryParms.pageNo++; // set to next page
return pretendAjaxFnc(queryParms); // get next page
})
这是一个可运行的例子:
function pretendAjaxFnc(obj) {
return Promise.resolve().then(function() {
if (obj.pageNo < 6) { // create a pretend "I'm done" point.
// return a couple dummy records
return [{ fld1: "data1", fld2: "data2" },
{ fld1: "data1", fld2: "data2" }];
} else {
// this is the exit criteria
// It will actually be 404 http status converted to a custom exception
throw new Error("NO-MORE-DATA");
}
});
};
function clientAccumulator() {
var namesList = [];
var queryParms = {
pageNo: 1
};
return pretendAjaxFnc(queryParms)
.then(function(retData) {
namesList.push.apply(namesList, retData); // append data to list
queryParms.pageNo++; // set to get next page
console.log("EIC.GTEST11 list.len: ", namesList.length);
return pretendAjaxFnc(queryParms);
})
// repeat until some exit criteria - like an exception
.then(function(retData) {
namesList.push.apply(namesList, retData);
queryParms.pageNo++;
console.log("EIC.GTEST21 list.len: ", namesList.length);
return pretendAjaxFnc(queryParms);
})
// repeat until some exit criteria - like an exception
.then(function(retData) {
namesList.push.apply(namesList, retData);
queryParms.pageNo++;
console.log("EIC.GTEST31 list.len: ", namesList.length);
return pretendAjaxFnc(queryParms);
})
// repeat until some exit criteria - like an exception
// ...
.catch(function(ex) {
if (ex.message === "NO-MORE-DATA") {
return namesList;
} else {
throw ex;
}
});
};
clientAccumulator(); // Run the function
这是需要在当前iOS / Safari&amp; Firefox(尽管更多的变化)。我正在使用AngularJS,但我相信我已经删除了任何特异性。
有人有.thenRepeat
他们可以指点我吗?
答案 0 :(得分:1)
递归是你的朋友。
重新阅读之后,似乎这可能更符合您的需求:
repeatPromiseUntil({
promiseMethod,
doneConditionMethod,
waitInterval = 100
}){
return promiseMethod()
.then((result) => {
if (doneConditionMethod(result)) {
return this.$q.resolve(result);
}
return this.$timeout(waitInterval)
.then(() => this.repeatPromiseUntil({promiseMethod, doneConditionMethod, waitInterval}));
});
}
这是我自己的代码中的一个例子(它是从这个答案的Typescript重写的,所以可能有一两个错字)
function retryPromise({
maxRetries,
promiseMethod,
successConditionMethod,
retryInterval,
increaseInterval = true
}) {
if (increaseInterval) {
retryInterval = retryInterval + 1000;
}
return promiseMethod().then((result) => {
if (successConditionMethod(result)) {
return $q.resolve(result);
} else if (maxRetries > 0) {
return $timeout(retryInterval)
.then(() => {
return retryPromise({
maxRetries: maxRetries - 1,
promiseMethod,
successConditionMethod,
retryInterval,
increaseInterval
});
});
} else {
retryInterval = 0;
return $q.reject();
}
});
}
编辑:我添加了一些我自己使用的角度细节(最初错过了有关角度的评论)
答案 1 :(得分:1)
只需将then链放入函数中,以便它是递归的:
function recurse() {
return pretendAjaxFnc(queryParams)
.then(function(retData) {
namesList.push(...retData);
queryParms.pageNo++;
return recurse();
});
}
工作示例:
function pretendAjaxFnc(obj) {
return Promise.resolve().then(function() {
if (obj.pageNo < 6) { // create a pretend "I'm done" point.
// return a couple dummy records
return [{ fld1: "data1", fld2: "data2" },
{ fld1: "data1", fld2: "data2" }];
} else {
// this is the exit criteria
// It will actually be 404 http status converted to a custom exception
throw new Error("NO-MORE-DATA");
}
});
};
function clientAccumulator2() {
var namesList = [];
var queryParms = {
pageNo: 1
};
console.log("TEST00 list.len: ", namesList.length);
function recurse() {
return pretendAjaxFnc(queryParms)
.then(function(retData) {
namesList.push(...retData);
console.log("TEST01 list.len: ", namesList.length);
queryParms.pageNo++;
return recurse();
});
}
return recurse()
// repeat until some exit criteria - like an exception
.catch(function(ex) {
if (ex.message === "NO-MORE-DATA") {
return namesList;
} else {
throw ex;
}
});
};
clientAccumulator2(); // Run the function