I have a piece of code that has to deal with some nested promises and shared variables between them. This code is complicated by itself and because of promises syntax is even more difficult to read for those that haven't written it.
The code right now is something like this:
const _deleteOneToOneRooms = function(userId, teamMembers) {
return function() {
return User.findOne({ _id: userId })
.then((userDeleted) => {
return Promise.all(teamMembers.map((member) => {
return User.findOne({ _id: member }).then((user) => {
return {
id: user._id,
commonTeams: Utils.arrayIntersect(user.teams, userDeleted.teams).length !== 0
};
});
}))
.then((usersNoCommonTeam) => {
return Promise.all(usersNoCommonTeam.map((user) => {
if(user.commonTeams) {
return Promise.resolve();
}
return Room.findOneAndRemove(
{
$and: [
{ type: 'one-to-one' },
{ owners: { $all: [user.id, userDeleted] } }
]
});
}));
});
})
.then((roomsToDelete) => {
return Promise.all(roomsToDelete.map((room) => {
if(room) {
return Membership.remove({ room: room._id });
}
return Promise.resolve();
}));
});
};
};
someDatabaseLookups.then(_deleteOneToOneRooms(userId, teamMembers))
I have considered to split each then into functions so the overall code is simpler to read:
const _deleteOneToOneRooms = function(userId, teamMembers) {
return function() {
return User.findOne({ _id: userId })
.then((deletedUser) => {
return _getUsersWithNoCommonTeams(deletedUser, teamMembers);
})
.then((usersNoCommonTeam) => {
return _getOneToOneRooms(userId, usersNoCommonTeam);
})
.then(_removeRooms);
};
};
But I don't like having one-line functions only to give them names and at the end if you are reading the code for the first time, you will have to scroll up and down to know what is being done, which from my point of view makes it harder to understand.
So my question is, is there a convention on how to write the cleanest code when dealing with complicated nested promises that use shared variables?
async/await
pattern that would greatly improve readability of your code? \$\endgroup\$