在下面的代码中,我尝试执行以下操作:
Stats()
,getOverallStats()
和GetGroups()
并行运行。每个都返回一个承诺。forEach
中的GetGroups.then()
应按顺序运行,以确保输出的顺序正确。然而,我对这些承诺感到非常困惑!记录给了我:
looping
here
looping
looping
但我要找的是here
到最后。
最后,目前我已将loopAgelist[1]
硬编码用于测试目的。但是,我实际上希望能够在loopAgelist[]
之间循环,并在两者之间超时!如果有人能解释一些在这些复杂案件中使用的承诺“规则”,我将不胜感激。
var loopAgeList;
var looppromises = [];
getAgeGroupList().then(function (loopAgeList) {
var statsPromise = Stats(loopAgeList[1]);
var oStatsPromise = getOverallStats();
var grpPromise = GetGroups(loopAgeList[1]).then(function (groups) {
var promise = Parse.Promise.as();
groups.forEach(function (grp) {
promise = promise.then(function () { // Need this so that the tables are drawn in the correct order (force to be in series)
console.log("looping")
if (grp != "KO"){
var standingsPromise = Standings(loopAgeList[1], grp);
looppromises.push(standingsPromise);
}
var fixPromise = GetFixtures(loopAgeList[1], grp);
looppromises.push(fixPromise);
return fixPromise;
});
});
return Parse.Promise.all(looppromises);
});
var promises = [statsPromise, oStatsPromise, grpPromise, looppromises];
Parse.Promise.all(promises).then(function(results) {
console.log("here");
});
});
答案 0 :(得分:1)
通过采用几个简单的样式规则可以显着改善重写:(1)不需要创建已解决的承诺然后链接到它(实际上,大多数人会认为这是反模式),(2)承诺通过迭代操作数组来一起运行是数组.map(不减少)的完美应用,(3)最重要的是,更小,可测试,承诺返回的函数总是清除这个谜。
把所有这些放在一起,主要功能可以像这样简单......
function loopOverOnce(agegroup) {
let statsPromise = Stats(agegroup);
let oStatsPromise = getOverallStats();
let grpPromise = GetGroups(agegroup).then(function(groups) {
return getStandingsAndFixturesForGroups(groups, agegroup);
});
return Parse.Promise.all([statsPromise, oStatsPromise, grpPromise]);
}
让我们写getStandingsAndFixturesForGroups
。它的唯一工作就是映射小组并聚合承诺,为每个小组做好工作......
function getStandingsAndFixturesForGroups(groups, agegroup) {
let promises = groups.map(function(group) {
return getStandingsAndFixturesForGroup(group, agegroup);
});
return Parse.Promise.all(promises);
}
现在,getStandingsAndFixturesForGroup
,一个在单个组上执行异步工作的函数,有条件地用于部分工作......
function getStandingsAndFixturesForGroup(group, agegroup) {
let promises = (group != "KO")? [ Standings(agegroup, grp) ] : [];
promises.push(GetFixtures(agegroup, group));
return Parse.Promise.all(promises); // this is your standings promise (conditionally) and fixtures promise
}
完成。我将按照与此处相反的顺序测试此代码。
编辑 OP还询问如何连续执行多项承诺,穿插超时。这是我的建议。
首先,你的延迟函数的一个稍微简单的版本,这是一个很好的例子,当 正确创建一个新的承诺时(因为没有任何东西可以调用来获得一个)
function delay(interval) {
return new Promise(function(resolve, reject){
setTimeout(function() {resolve();}, interval);
});
};
减少是建立承诺列表的好方法,包括散布的延迟......
getAgeGroupList().then(function (loopAgeList) {
loopAgeList.reduce(function(promise, agegroup) {
return promise.then(function() {
let promises = [loopOverOnce(agegroup), delay(15000)];
return Promise.all(promises);
});
}, Promise.as());
});
一些注意事项:这会产生一个类似loopOverOnce,timeout,loopOverOnce,timeout等等的序列。如果你想先超时,那就颠倒内循环中小链的顺序:
[ delay(15000), loopOverOnce(agegroup) ]
最后要注意的是,通过对匿名函数采用ES6胖箭头语法,所有这些都可以做得更短更漂亮。
loopAgeList.reduce((promise, agegroup) => {
promise.then(() => Promise.all([loopOverOnce(agegroup), delay(15000)]));
}, Promise.as());
答案 1 :(得分:0)
问题是,您将嵌套数组传递给Promise.all:
var promises = [statsPromise, oStatsPromise, grpPromise, looppromises];
简单地说:
var promises = [statsPromise, oStatsPromise, grpPromise, ...looppromises];
// Or
var promises = [statsPromise, oStatsPromise, grpPromise].concat(looppromises);
但是你仍然需要在某个地方等待promise
以确保链完成执行,否则looppromise
将为空。
总而言之,使用async / await使一切更具可读性可能更好:
(async function() {
const ageGroups = await getAgeGroupList();
const statsPromise = Stats(ageGroups[1]);
const overallStatsPromise = getOverallStats();
const groups = await GetGroups(ageGroups[1]);
for(const group of groups) {
const [standings, fixtures] = await Promise.all(
Standings(ageGroups[1], group),
GetFixtures(ageGroups[1], group)
);
// Do something with standings & fixtures
}
const [stats, overallStats] = await Promise.all(statsPromise, overallStatsPromise);
// Do whatever you want with stats etc.
})();
答案 2 :(得分:0)
我已使用reduce
重新编写它,似乎让它正常工作。欢迎提出这方面的意见(即此代码是否存在任何问题)。
function loopOverOnce(agegroup) {
var statsPromise = Stats(agegroup);
var oStatsPromise = getOverallStats();
var grpPromise = GetGroups(agegroup).then(function (groups) {
function getStandingsAndFixtures(groups) {
var promise = Parse.Promise.as();
return groups.reduce(function (promise, grp) {
return promise.then(function (result) {
var standingsPromise = Parse.Promise.as();
if (grp != "KO") {
standingsPromise = Standings(agegroup, grp);
}
var fixPromise = GetFixtures(agegroup, grp);
console.log("fixPromise");
return Parse.Promise.all([standingsPromise, fixPromise]);
});
}, promise);
}
var sfPromise = getStandingsAndFixtures(groups).then(function () { console.log("Test1") });
return sfPromise;
});
return Parse.Promise.all([statsPromise, oStatsPromise, grpPromise]).then(function () { console.log("Test2") });
}
getAgeGroupList().then(function (loopAgeList) {
// https://stackoverflow.com/questions/39538473/using-settimeout-on-promise-chain
function delay(t, v) {
return new Promise(function (resolve) {
setTimeout(resolve.bind(null, v), t)
});
}
var promise = Parse.Promise.as();
loopAgeList.reduce(function (promise, agegroup) {
return promise.then(function () {
return delay(15000).then(function () {
return loopOverOnce(agegroup);
});
});
}, promise);
});