Я анализирую массив файлов и отправляю их в базу данных. Как часть этого, мне нужно вести итоги данных в файлах и количество успешных вставок записей в базу данных. Обещание не ждет, пока все записи будут записаны в базу данных.

Я ищу метод parserResults, чтобы вернуть testResults обратно вызывающему .reduce. Он передает его обратно, но insertSuccess = 0.

Я ввел несколько журналов консоли, чтобы увидеть, что она делает, и окончательный результат отображается на консоли до того, как увеличится счетчик успешной вставки.

Console.log результаты

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

Это код, вызывающий функцию, которая будет анализировать файлы.

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

Вот вызываемый метод

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

Я играл с несколькими разными сценариями в коде и, кажется, не могу понять это. Любая помощь будет принята с благодарностью. Спасибо кристина

1
Christine Edwards 15 Фев 2018 в 04:18

1 ответ

Лучший ответ

parseResults() неправильно возвращает обещание, поэтому ваш p.then() внутри цикла .reduce() ничего не ждет.

Измените это:

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

К этому:

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

Код, который вы использовали: return (Promise.all(results), testResults); возвращал только testResults, а не обещание. Я думаю, вам нужно знать, когда все обещания выполнены, а затем сделать testResults разрешенным значением. Для этого вы используете .then() в Promise.all(), а затем возвращаете testResults из этого обработчика .then(). Это вернет одно обещание, разрешенное значение которого равно testResults.

К вашему сведению, вам может вообще не понадобиться это делать, потому что testResults, похоже, является переменной с более высокой областью действия, на которую вы могли бы просто ссылаться напрямую. Если вы готовы это сделать, вам просто нужно изменить на:

return Promise.all(results);

И тогда не используйте finalResult в вашем последнем обработчике .then(), просто обратитесь напрямую к переменной testResults с более высокой областью видимости.


К вашему сведению, более чистая реализация этого могла бы передать объект, который каждая итерация цикла возвращает и передает на следующую итерацию, чтобы вообще не было ссылки на переменную с более высокой областью действия, и все было более самодостаточным. Затем вы использовали бы первый тип возврата, который я вам показал, но вы бы вернули переданный объект, а не объект с более высокой областью видимости.

2
jfriend00 15 Фев 2018 в 04:43