首页 > 解决方案 > 使用顺序 for 循环解析多链承诺

问题描述

在下面的代码中,我正在尝试执行以下操作:

但是,我对这些承诺感到非常困惑!日志记录给了我:

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

标签: javascriptparse-platformpromise

解决方案


通过采用几个简单的样式规则可以显着改进重写:(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());

推荐阅读