承诺在回国前不解决

时间:2018-03-06 02:38:52

标签: javascript promise reduce

我很难弄清楚承诺是如何运作的。我有以下代码,我正在执行迭代数组。



runOpts.automationResults.reduce(function (p, val) {
        return p.then(function () {
              return  pd.run(val);
});
}, Promise.resolve()).then(function (rallyResults) {
     console.log('returned from method');
     console.log('rallyResults ', rallyResults);
}, function (err) {
     console.log('error in reduce', err);
});




它正在调用以下方法



ProcessDatabase.prototype.run = function (options) {
    return new Promise((resolve, reject) => {
        var dal = new db();
        var resultsArray = {
            results: [],
            options: [],
            testSet: [],
            testIteration: '',
            multipleSets: 0,
            totalCount: 0
        }
        resultsArray.options = options;
        dal.getAutomationResultsByBuild(options.Build).then((results) => {
            resultsArray.results = results;
            resultsArray.totalCount = results.data.length;
            resolve(resultsArray);
        })
    }).then(function (resultsArray) {
        var results = [];
        //console.log('resultsArray', resultsArray);
        //console.log(`Starting Rally publishing for Build '${resultsArray.options.Build}'...`)

        if (resultsArray.options.Executiontype == 'ci') {

            rallyApi.autoDiscoverTestSets().then((sets) => {
                resultsArray.testSet = sets.sets;
                resultsArray.testIteration = sets.iteration;
                resultsArray.multipleSets = sets.sets.length > 1;
                results.push(resultsArray);
                console.log('results', results);
            }, (err) => { reject(err); });
            // totalResults = totalResults + results.data.length;
        } else {
            rallyApi.addTestSet('Automation: ' + resultsArray.options.type + ' - ' + resultsArray.options.build, config.get('rally.projects.testing.ref'), null, resultsArray.options.SessionUser).then((resp) => {
                //console.log(resp);
                console.log('New test set ' + resp.FormattedID + ' created.');
                resultsArray.multipleSets = 0;
                resultsArray.testSet = resp.FormattedID;
                //console.log('resultsArray', resultsArray);
                results.push(resultsArray);
                console.log('results', results);
            }, (err) => {
                console.log(err);
            });
        }

        console.log('results', results);
        return Promise.all(results);

    })
}




我已经尝试了几次不同的迭代,我总是在ProcessDatabase.prototype.run方法中完成结果之前返回到调用.reduce。

我已经安装了控制台日志,这就是我得到的。我可以看到最终的结果数组包含了我需要的所有信息。我还没有能够弄清楚如何将它传递回调用.reduce。



---These are actually from the .reduce and are written to the log before the results in the method called
returned from method 
rallyResults  [] 

**----These are from the ProcessDatabase.prototype.run method called**
**This is the contents of the "results" set the first iteration through**
-- Found 2 test sets.
results [ { results: { _success: true, _message: '', _data: [Array] },
    options:
     { Executiontype: 'ci',
       Build: 'test_030518_103956',
       Environment: 'dev',
       SessionUser: 'https://rally1.rallydev.com/slm/webservice/v2.0/user/165547093296' },
    testSet: [ [Object], [Object] ],
    testIteration: 'https://rally1.rallydev.com/slm/webservice/v2.0/iteration/184203152680',
    multipleSets: true,
    totalCount: 4 } ]
New test set TS2969 created.

**This is the contents of the "result" set after the second iteration 
through and what I trying to get passed back to the calling .reduce.**

results [ { results: { _success: true, _message: '', _data: [Array] },
    options:
     { Executiontype: 'ci',
       Build: 'test_030518_103956',
       Environment: 'dev',
       SessionUser: 'https://rally1.rallydev.com/slm/webservice/v2.0/user/165547093296' },
    testSet: [ [Object], [Object] ],
    testIteration: 'https://rally1.rallydev.com/slm/webservice/v2.0/iteration/184203152680',
    multipleSets: true,
    totalCount: 4 },
  { results: { _success: true, _message: '', _data: [Array] },
    options:
     { Executiontype: 'regression',
       Build: 'test_030518_110447',
       Environment: 'dev',
       SessionUser: 'https://rally1.rallydev.com/slm/webservice/v2.0/user/165547093296' },
    testSet: 'TS2969',
    testIteration: '',
    multipleSets: 0,
    totalCount: 6 } ]
    




任何帮助都会非常感激。 谢谢 恭

1 个答案:

答案 0 :(得分:2)

此代码中存在许多问题,但主要的问题是当您在.then()处理程序中运行另一个异步操作时,您必须从.then()返回该承诺才能获得它正确地链接到主要的承诺链。如果你不这样做,那么父承诺根本没有链接到那个内部承诺(它成为它自己的独立承诺链,你无法监控它),而且父承诺不会等待内部承诺。

以下是所做的更改:

  1. 在另一个承诺中删除不必要地包含承诺的承诺反模式(只需返回您已经拥有的承诺)
  2. 从.then()处理程序中返回嵌套的promises以正确链接它们
  3. 在一个位置合并错误记录并重新抛出错误,以便正确返回
  4. 删除Promise.all()
  5. 删除results.push(resultsArray);,因为似乎没有任何意义。我在下面编写代码的方式,顶级承诺解析为resultsArray,因为只有其中一个,我认为不需要将它嵌入另一个数组中。
  6. 以下是修改后的代码:

    ProcessDatabase.prototype.run = function (options) {
        var dal = new db();
        var resultsArray = {
            results: [],
            options: {},
            testSet: [],
            testIteration: '',
            multipleSets: 0,
            totalCount: 0
        }
        resultsArray.options = options;
        return dal.getAutomationResultsByBuild(options.Build).then((results) => {
            resultsArray.results = results;
            resultsArray.totalCount = results.data.length;
            return resultsArray;
        }).then(function (resultsArray) {
            //console.log('resultsArray', resultsArray);
            //console.log(`Starting Rally publishing for Build '${resultsArray.options.Build}'...`)
    
            if (resultsArray.options.Executiontype == 'ci') {
    
                return rallyApi.autoDiscoverTestSets().then((sets) => {
                    resultsArray.testSet = sets.sets;
                    resultsArray.testIteration = sets.iteration;
                    resultsArray.multipleSets = sets.sets.length > 1;
                    return resultsArray;
                });
            } else {
                return rallyApi.addTestSet('Automation: ' + resultsArray.options.type + ' - ' + resultsArray.options.build, config.get('rally.projects.testing.ref'), null, resultsArray.options.SessionUser).then((resp) => {
                    //console.log(resp);
                    console.log('New test set ' + resp.FormattedID + ' created.');
                    resultsArray.multipleSets = 0;
                    resultsArray.testSet = resp.FormattedID;
                    return resultsArray;
                });
            }
    
        }).catch(err => {
            // log error and rethrow
            console.log(err);
            throw err;
        });
    }