0

I am still trying to understand synchronicity in JS. The following script can log different values. How can I ensure it to log a stable value? Appreciate any helps.

// variable "all" is the array which holds the file path as string
all.forEach(async(f) => {
    promise = new Promise((resolve, reject) => {
        fs.readFile(f, 'utf8', function (err, content) {
            if (!err) {
                scenario += (content.match(/Scenario(\s?)\(\'/g) || []).length;
                uc += (content.match(/\/\/(\s?)UC-(.)+/g) || []).length;
                resolve([scenario, uc]);
            } else {
                reject('Error!');
            }
        });
    });
    await promise;
});

promise.then(([scenario, uc]) => {
    console.log('Total Scenarios: ' + scenario);
    console.log('Total UCs: ' + uc);
});

Edit: Following code works correctly for me

As taking reference of @Yftach and @Manjeet Thakur responses.

This code works correctly for me;

let promises = all.map(f => {
        return new Promise((resolve, reject) => {
            fs.readFile(f, 'utf8', function (err, content) {
                if (!err) {
                    scenario += (content.match(/Scenario(\s?)\(\'/g) || []).length;
                    uc += (content.match(/\/\/(\s?)UC-(.)+/g) || []).length;
                    resolve([scenario, uc]);
                } else {
                    reject('Error!');
                }
            });
        });
    });

    Promise.all(promises).then((result) => {
        let max = result.reduce((acc, curr) => {
            return [Math.max(acc[0],curr[0]), Math.max(acc[1],curr[1])];
        });

        console.log('Total Scenarios: ' + max[0]);
        console.log('Total UCs: ' + max[1]);
    });
});
tewoos
  • 45
  • 2
  • 10

2 Answers2

2

Your code will not work because you only wait for one promise, what you should do is use Promise.all(arrayOfPromises), this method will return a new promise that runs only after all the promises in the array are completed.

let allPromises = all.map((f) => {
    promise = new Promise((resolve, reject) => {
        fs.readFile(f, 'utf8', function (err, content) {
            if (!err) {
                scenario += (content.match(/Scenario(\s?)\(\'/g) || []).length;
                uc += (content.match(/\/\/(\s?)UC-(.)+/g) || []).length;
                resolve({scenario:scenario, uc:uc});
            } else {
                reject('Error!');
            }
        });
    });
    return promise;
});

Promise.all(allPromises).then((values) => {
    // Sum all the scenarios and UCS, becase the values is an array of objects representing answers from each promise, we must sum them ourselves
    console.log('Total Scenarios: ' + values.reduce((accumulated, current) => accumulated + current.scenario, 0);
    console.log('Total UCs: ' + values.reduce((accumulated, current) => accumulated + current.uc, 0););
});

Note: the "all" promise will be rejected if one of the inner promises rejects, so in case you would want to ignore that case and sum the rest of the promises, you would need to resolve the promise with a "empty" values and then take care of that in the summation in the final then.

Yftach
  • 712
  • 5
  • 15
0
var promises = all.map(f => {
    return new Promise((resolve, reject) => {
        fs.readFile(f, 'utf8', function (err, content) {
            if (!err) {
                scenario += (content.match(/Scenario(\s?)\(\'/g) || []).length;
                uc += (content.match(/\/\/(\s?)UC-(.)+/g) || []).length;
                resolve([scenario, uc]);
            } else {
                reject('Error!');
            }
        });
    });
});

Promise.all(promises).then(([scenario, uc]) => {
    console.log('Total Scenarios: ' + scenario);
    console.log('Total UCs: ' + uc);
});
Manjeet Thakur
  • 2,288
  • 1
  • 16
  • 35