javascript - 使用顺序 for 循环解析多链承诺
问题描述
在下面的代码中,我正在尝试执行以下操作:
- 有
Stats()
,getOverallStats()
和GetGroups()
并行运行。每个都返回一个承诺。 forEach
in应该按顺序运行以确保输出的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");
});
});
解决方案
通过采用几个简单的样式规则可以显着改进重写:(1)没有必要创建一个已解决的承诺然后链接到它(事实上,大多数人会认为这是一种反模式),(2)承诺是通过迭代操作数数组一起运行是数组.map(不是reduce)的完美应用,(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、超时、loopOverOnce、超时等的序列。如果您想先超时,请反转内部循环中小链的顺序:
[ delay(15000), loopOverOnce(agegroup) ]
最后一点是,通过对匿名函数采用 ES6 胖箭头语法,所有这些都可以变得更短更漂亮,例如
loopAgeList.reduce((promise, agegroup) => {
promise.then(() => Promise.all([loopOverOnce(agegroup), delay(15000)]));
}, Promise.as());
推荐阅读
- mongodb - Mongo 连接器当前不支持级联删除
- asp.net-core-mvc - MVC CORE SignalR 仅向特定用户发送消息
- python - “只能将str(而不是“builtin_function_or_method”)连接到str”是什么意思?
- android - Flutter & Firestore:app.INotificationSideChannel$Stub$Proxy 错误
- r - 使用 dplyr 库通过 R 管道运行代码时出错
- javascript - 预期的模拟函数被调用了一次,但它被调用了零次。如何解决?
- javascript - Clippath 在 Google Chrome 应用程序中没有响应
- excel - 用 IF 和 AND 独立测试值
- vue.js - 如何让这些 Flexbox 列简单地工作?
- laravel - 同一个模型的多个数据存储(数据库和json),怎么做?