简体   繁体   中英

promise not resolving before return

I am parsing through an array of files and posting to the database. As part of that, I need to keep totals of the data in the files, and a count of successful record insertions into the database. The promise is not waiting for all the records to be written to the database.

I am looking for the parserResults method to return the testResults back to the calling .reduce. It does pass it back, but the insertSuccess = 0.

I put in some console logs to see what it is doing and the finalResult is displaying on the console before the incremented insertSuccess counter is incremented.

Console.log results

 In parseresults ui-results-11705.json In parseresults ui-results-14981.json In parseresults ui-results-14982.json In parseresults ui-results-28274.json In parseresults ui-results-368.json finalResult = { insertSuccess: 0, insertFailed: 0, testPassedCount: 2, testFailedCount: 3 } insertSuccess 1 insertSuccess 2 insertSuccess 3 insertSuccess 4 insertSuccess 5 

This is the code calling the function that will parse the files

  matches.reduce(function (p, val) { return p.then(function () { console.log('p', p); return parser.parseResults(val); }); }, Promise.resolve()).then(function (finalResult) { console.log('finalResult = ', finalResult); }, function (err) { console.log('error in reduce', err); }); 

Here is the method being called

 protractorParser.prototype.parseResults = function (fileName) { return new Promise((resolve, reject) => { console.log('In parseresults', fileName); var currentFile = './testing/results/' + fileName json.readFile(currentFile, function (err, obj) { if (err != null) { console.log('error reading file', err); reject(err); } else { resolve(obj); } }); }).then(function (obj) { var results = []; for (var suite in obj) { var specs = obj[suite].specs; for (let i = 0; i < specs.length; i++) { const assert = specs[i]; const tcR = /TC[\\d]+/; const tc = assert.description.match(tcR); let Passed = 1; let Message = ''; let Stack = ''; if (assert.failedExpectations.length) { const expectation = assert.failedExpectations[assert.failedExpectations.length - 1]; Passed = 0; Message = expectation.message; Stack = expectation.stack.split('\\n')[1].trim(); testResults.testFailedCount++ } else { testResults.testPassedCount++ } if (tc != null) { const time = moment().utcOffset(config.get('settings.timeOffset')).format('YYYY-MM-DDTHH:mm:ss'); const promise = utility.TestDataManager.insertAutomationResults(tc[0], assert.description, Passed, process.env.testBuild, 'P', Message, Stack, 0, time, ''); results.push(promise.then(() => { testResults.insertSuccess++; console.log('insertSuccess', testResults.insertSuccess); }, err => { console.log('… failed', err); throw err; } )); } else { console.log('no test case found for test: ' + assert.description + ' -- skipping'); // I don't think you want to `throw err` here, right? } } } return (Promise.all(results), testResults); }); }; 

I have played around with several different scenarios in the code and can't seem to figure it out. Any help would be greatly appreciated. Thanks Christine

parseResults() is not properly returning a promise, therefore your p.then() inside the .reduce() loop doesn't wait for anything.

Change this:

return (Promise.all(results), testResults);

to this:

return Promise.all(results).then(() => testResults);

The code you were using: return (Promise.all(results), testResults); was only returning testResults , not a promise. What I think you want is to know when all the promises are done and then to make testResults be the resolved value. To do that, you use .then() on the Promise.all() and then return testResults from that .then() handler. That will return a single promise whose resolved value is testResults .

FYI, you may not need to do that at all because testResults appears to be a higher scoped variable that you could just refer to directly. If you're willing to do that, then you would just change to:

return Promise.all(results);

And, then don't use finalResult in your final .then() handler, just refer to the higher scoped testResults variable directly.


FYI, a cleaner implementation of this could pass in an object that each iteration of the loop returns and passes on to the next iteration so there's no reference at all to a higher scoped variable and everything is more self contained. Then, you would use the first type of return I showed you, but you'd return the passed in object, not the higher scoped object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM