Promises, like callbacks, allow asynchronous operations to be performed in parallel. And they can do it automatically, without having to manually track where one of the operations end. All you need to do is collect an array of promises and pass them to the Promise.all
function. As a result, the usual promise will be returned, which you can use to build a chain further. The data in the first then
will be an array with the data of all operations performed.
import fsp from 'fs/promises';
const unionFiles = (inputPath1, inputPath2, outputPath) => {
const promise1 = fsp.readFile(inputPath1, 'utf-8');
const promise2 = fsp.readFile(inputPath2, 'utf-8');
// The input is an ARRAY of promises
const promise = Promise.all([promise1, promise2]);
// Don't forget to return!
return promise.then(([data1, data2]) => fsp.writeFile(outputPath, `${data1}${data2}`));
};
The result is effective code that's also easy to understand. And there are no additional variables here. Although Promise.all
returns the data in the same order that the promises were passed to it in, it doesn't guarantee the sequence of operations. Don't ever count on it, all operations run simultaneously, and which operation will be running earlier or later is unknown.
The Promise.all
all function doesn't care how the Promise collection was obtained. The only thing it needs is to get an array of those promises as input. So Promise.all
can easily be combined with any function that returns collections. The example below is an array of paths to the files that need to be read and have their contents displayed. The first thing in the code is to form an array of promisses, then it is passed to Promise.all
and finally the contents of the files are displayed on the screen:
// promises is an array of promises
const promises = filepaths.map((filepath) => fsp.readFile(filepath, 'utf-8'));
const promise = Promise.all(promises);
// Display the contents of each file
promise.then((contents) => contents.map(console.log));
map
goes through each file and sends it to our function, which calls fsp.readFile()
. Each such call returns a promise. If you try to print this array, it'll look like this:
const promises = filepaths.map((filepath) => fsp.readFile(filepath, 'utf-8'));
console.log(promises);
[
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
...
]
Promise.all
always runs operations simultaneously, and these operations don't depend on each other in any way. This means that no error (other than the program stopping) will stop requests. An error in at least one of the promises won't prevent all the other requests from being executed. However, if at least one promise fails, the whole result of Promise.all
will be marked as erroneous and thus control will fall to the next catch
. To avoid this, it is possible to transfer to the Promise.all
not just promises, but promises with error handlers attached to them catch
, from which the data is already returned with a success mark.
const promises = filepaths.map((filepath) => fsp.readFile(filepath, 'utf-8')
.then((v) => ({ result: 'success', value: v }))
.catch((e) => ({ result: 'error', error: e })));
const promise = Promise.all(promises);
The Hexlet support team or other students will answer you.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.
Programming courses for beginners and experienced developers. Start training for free
Our graduates work in companies:
From a novice to a developer. Get a job or your money back!
Sign up or sign in
Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.