Cyber Lis Cyber Lis - 11 months ago 40
Javascript Question

How do i run async Promises without promise hell?

I want get files in directory, open them, process them, and write result.
I want do all step async with Promises

First thing came to my head was

read_dir('/tmp')
.then(function(files){
for(var i=0; i<files.length; i++){
read_file(files[i])
.then(function(file_data){
var processed_data = process_work_convert(file_data.data);
return {'filename': file_data.name, 'data': processed_data}
})
.then(function(file_data){
return write_file(file_data.filename, file_data.data);
})
.then(function(){
console.log('success');
})
}
})


But it looks like standard callback way (callback hell)

I can use
Promise.all
but it will make my code synchronous

I want some magic
then_each
and
catch_each


example:

read_dir('/tmp')
.then_each(function(file){
return read_file(file);
})
.then_each(function(file_data){
var processed_data = process_work_convert(file_data.data);
return {'filename': file_data.name, 'data': processed_data}
})
.then_each(function(file_data){
return write_file(file_data.filename, file_data.data);
})
.then_each(function(){
console.log('success');
})
.catch_each(function(){
console.log('error');
});


Does this function exist ?

Or may be you know how extend Promise to achive this?

Or may be there is some othe way to do this?

Answer Source

The code you are looking for is

read_dir('/tmp')
.then(function(files){
    return Promise.all(files.map(function(file) {
        return read_file(file)
        .then(function(file_data) {
            return write_file(file_data.name, process_work_convert(file_data.data));
        });
    }));
})
.then(function(){
    console.log('success');
}, function(e){
    console.log('error', e);
});

There is no callback hell here, just some extra indentation from the looping.

If you want to do with less callbacks, have a look at the upcoming async/await syntax:

(async function() {
    var files = await read_dir('/tmp');
    await Promise.all(files.map(async function(file) {
        var file_data = await read_file(file);
        await write_file(file_data.name, process_work_convert(file_data.data));
    }));
    console.log('success');
}())
.catch(function(e){
    console.log('error', e);
});

Does this function exist?

No, it cannot (at least without the synchronisation that you are trying to avoid).